Mysql死锁问题

最近遇到一个mysql抖动的问题,看写库的load和io其实都不高,但是会有突然的活跃链接的激增,查下来是发生了循环的死锁,以前不太了解这块知识,稍微看了一下,在这边总结下。

INNODB通过MVCC实现了事务
在并发的环境中会有如下问题
1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据。
2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
3、幻读:事务A依据条件批量读取或修改一批数据,事务B在A读取修改的过程中,插入了新的符合条件的数据,事务A读取或修改结束后发现少读/改动一条数据。

INNODB中不同的事务隔离级别会产生不同的锁机制,也会靠锁来解决部分问题
查询事务隔离方法:

mysql> show variables like '%isolation%';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | READ-COMMITTED  |
+---------------+-----------------+
隔离级别 脏读 不可重复读 幻读
READ-UNCOMMITTED yes yes yes
READ-COMMITTED no yes yes
REPEATABLE-READ no no yes
SERIALIZABLE no no no

我的表是READ-COMMITTED,也就是不会发生脏读,但会出现不可重复读和幻读的情况。

有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。当数据对象被加上排它锁时,其他的事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取,但不能修改。

当X锁和S锁同时发生时候在某一行上会发生死锁。具体来说,事务A查询一条纪录,然后修改该条纪录;这时事务B修改该条纪录,这时用户A的事务里锁的性质由查询的共享锁企图上升到排它锁,而用户B里的排它锁由于A 有共享锁存在所以必须等A释放掉共享锁,而A由于B的排它锁而无法上升的排它锁也就不可能释放共享锁,于是出现了死锁。sql本身会试图解锁,但会带来具体开销,应该从代码层就避免这种情况发生。

我的情况就是多个异步任务试图去操作同一条数据,导致了死锁。

猜你喜欢

转载自blog.csdn.net/weixin_41571449/article/details/80375904
今日推荐