MYSQL数据库模拟队列实现

本文通过实例演示了如何使用MySQL数据库模拟队列实现,详细介绍了不同事务隔离级别下的并发消费行为,特别是REPEATABLE-READ隔离级别下出现的神奇现象,并提出了处理中断和僵尸数据的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


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

mysql> set session transaction isolation level REPEATABLE READ;



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



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

mysql> start transaction;




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

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



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

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


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

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



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




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


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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值