MySQL单表模拟锁的有哪些情景
发布时间:2022-01-11 04:29:25 所属栏目:MySql教程 来源:互联网
导读:这篇文章主要介绍MySQL单表模拟锁的有哪些场景,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完! 在MySQL中对于并发,锁问题总是会有很多值得讨论的地方,但是通常来说,要模拟这些锁或者一些锁的问题需要花点功夫,比如创建多个表,
这篇文章主要介绍MySQL单表模拟锁的有哪些场景,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完! 在MySQL中对于并发,锁问题总是会有很多值得讨论的地方,但是通常来说,要模拟这些锁或者一些锁的问题需要花点功夫,比如创建多个表,创建大量的数据,然后像调试钟表的秒针一样,让问题刚好复现在哪个时间点上。如果换一个角度,单表来模拟这类而是可以吗,其实是可行的。 今天简单通过单表的测试模拟死锁,事务中的隐式提交(其实可以理解是个bug),间隙锁。 初始化数据 首先的准备工作就是初始化数据,我们创建一个表test,事务隔离级别为默认的RR。 建表语句: create table test( id int not null , name int , primary key(id), unique key(name) ) engine=innodb; 事务隔离级别: mysql> show variables like '%isolation%'; +---------------+-----------------+ | Variable_name | Value | +---------------+-----------------+ | tx_isolation | REPEATABLE-READ | +---------------+-----------------+ 1 row in set (0.00 sec) 除此之外就是打开两个窗口,我们简称为会话1,会话2. 模拟死锁 我们开始先模拟一下死锁问题。 会话1: 我们开启一个事务,插入一行记录,数据就选做今天的日期吧。 mysql>begin; mysql> insert into test values(2017,827); Query OK, 1 row affected (0.01 sec) 会话2; mysql> insert into test values(2016,827); 这个时候会话2会阻塞,这个时候有一种特殊的情况,那就是阻塞超时,如果超时,会自动停止。 会话1: mysql> insert into test values(2018,826); Query OK, 1 row affected (0.00 sec) 可见会话1中的DML操作依旧是可以的。 会话2: mysql> insert into test values(2016,827); 为了基于上面的测试数据,让两条数据成功插入,我们在会话2中结束事务。 mysql>commit; 然后开始做意料之外的事务自动提交测试,这一次我们在同一个会话中测试即可。问题的背景是如果我们显式声明事务,在同一会话中做了DML操作,没有提交,如果再开启一个事务,之前的事务会自动提交。 会话1: 这是基于场景1的测试之后的数据情况。 mysql> select *from test; +------+------+ | id | name | +------+------+ | 2018 | 826 | | 2017 | 827 | +------+------+ 2 rows in set (0.00 sec) 我们显式声明一个事务。 mysql> begin; Query OK, 0 rows affected (0.02 sec) 然后插入一条记录,重新给一个日期。 mysql> insert into test values(2019,825); Query OK, 1 row affected (0.00 sec) 这个时候没有提交,我们在当前会话中重新再开启一个事务。 mysql > begin; mysql > insert into test values(2015,830); 这个时候如果在会话2中查看,其实会发现,事务已经帮你提交了。 mysql> select *from test; +------+------+ | id | name | +------+------+ | 2018 | 826 | | 2017 | 827 | +------+------+ 2 rows in set (0.00 sec) 在会话1我们继续回滚事务,会发现于事无补。 mysql> rollback; Query OK, 0 rows affected (0.01 sec) 这个时候数据已经自动提交了一部分。 mysql> select *from test; +------+------+ | id | name | +------+------+ | 2018 | 826 | | 2017 | 827 | +------+------+ 2 rows in set (0.00 sec) 间隙锁测试 上面的测试场景其实还是多多少少都有些关联,其中第一个场景和间隙锁也有关系,我就简单用单表模拟一下间隙锁。 首先还是保证事务隔离级别是RR,因为间隙锁是RR隔离级别特供,RC中就没有间隙锁这样的定制,在并发场景中还是有不小的影响。我们来看看效果。 会话1: mysql> begin; Query OK, 0 rows affected (0.00 sec) 指定数据范围,然后显示声明。 mysql> select id from test where id <2019 lock in share mode; +------+ | id | +------+ | 2018 | | 2017 | +------+ 2 rows in set (0.00 sec) 会话2: 会话2中也开启一个事务,插入一条记录。结果就被阻塞了。 mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> insert into test values(2016,829); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 直到事务超时才作罢。 以上是“MySQL单表模拟锁的有哪些场景”这篇文章的所有内容,感谢各位的阅读! (编辑:威海站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |