MYSQL数据库模拟队列实现

时间:2024-03-12 22:21:09

1、首先MYSQL数据库的默认事务隔离级别为:REPEATABLE-READ 可重复读。


2、如果不是上述隔离级别,请先修改隔离级别为可重复读,修改方法如下:

mysql> set session transaction isolation level REPEATABLE READ;

MYSQL数据库模拟队列实现


3、开启两个命令行窗口,分别登录mysql,并命名为session1和session2,以模拟两个消费者消费模拟队列的数据(已提前保存好6条队列数据,不再模拟生产者的行为)。注释:id为自增主键、session用来存储sessionId,msg是待消费的数据体,status是消费状态(un_use:未消费,using:消费中,used:已消费)。

MYSQL数据库模拟队列实现


4、分别在SESSION1和SESSION2中开启事务,并查询此时队列中的数据状态,可以看到全部为un_use状态。

mysql> start transaction;

MYSQL数据库模拟队列实现

MYSQL数据库模拟队列实现


5、现在开始消费,session1先消费,假设每次消费2条。

mysql> update user set session=CONNECTION_ID(),status='using' where status='un_use' limit 2;

MYSQL数据库模拟队列实现


6、假如此时session2并发消费消息

情况(1)如果session1还没有commit事务,session2需要等待,一直等到session1提交事务(见情况(2)),或者session2超时回滚或重试。

MYSQL数据库模拟队列实现

情况(2)如果session1已经commit事务,则神奇的一幕出现了。

可以看到:session2执行update语句更新数据,更新的是id=1008,1009的两条消息!!!(讲道理应该更新1006,1007,为什么会更新1008和1009呢?除非,session2感知到了1006和1007被session1更新过了,但是从select结果上看,session2并没有感知到1006和1007已变化,这是一个神奇的东西,或许和MVCC有关,请懂的大牛们指教!)

MYSQL数据库模拟队列实现


7、既然如此,session1和session2都拿到了自己应该处理的消息,那就可以进行消息处理了,处理完消息以后,通过id来更新数据库状态就不存在并发问题了。

MYSQL数据库模拟队列实现

MYSQL数据库模拟队列实现


8、通过上面两session交替执行更新,可以进行并发更新,周而复始。


9、如果执行过程中session中断,则会造成一部分using状态的数据变成僵尸数据,此时可以结合定时任务,对using数据进行进行扫描。