共享锁:也就是读锁。 可以支持多个用户同时读。
排他锁:也就是写锁。
一、
一个用户A操作表A,又访问表B。 另一个用户B操作表B,又访问表A。就有可能用户A等待表B锁的释放,用户B等待表A的释放。两者都在等待对方,导致了死锁。

解决方法:调整逻辑访问顺序一致。

二、
用户A查询一条记录,然后修改该记录。用户B也查询该记录,然后也企图修改该记录。锁从读锁升级为写锁。
A在等待B的读锁释放。 B在等待A的死锁释放。

解决方法:乐观锁与悲观锁。

乐观锁:每次访问读取不上锁,乐观的认为不会修改访问的数据不会与其他用户冲突。当提交时,去查看有没有人动过相关数据,有别人动过则回滚重试。没有其他人动过则提交。

悲观锁:每次访问读取都上锁。悲观的认为会此数据会被别人修改。

三、
应该还有很多,按情况分析。这里就不想了。

总结死锁情况应该就两种
一种是顺序问题,另一种是锁的升级问题。

第一种死锁演示:
mysql 死锁情况
第二种死锁演示:
mysql 死锁情况
知识点:
1.发生死锁后,InnoDB一般都能自动检测到,并使一个事务释放锁并回退,另一个事务获得锁,继续完成事务。InnoDB并不能完全自动检测到死锁,这需要通过设置锁等待超时参数 innodb_lock_wait_timeout来解决。需要说明的是,这个参数并不是只用来解决死锁问题,在并发访问比较高的情况下,如果大量事务因无法立即获得所需的锁而挂起,会占用大量计算机资源,造成严重性能问题,甚至拖跨数据库。
2.Innodb的行锁是基于索引来实现的,如果不通过索引访问数据,Innodb会使用表锁。
3.死锁很难完全避免,应捕获并处理死锁异常,并尽量减少死锁的产生。

减少死锁的优化:
尽量使用较低的隔离级别。
尽量使用索引访问数据,使加锁更加精确。
尽量使用小事务。
尽量使用相同的顺序访问表。
尽量一次申请足够级别的锁,如先查一行再改改行,最好在查的时候就申请排他锁。

在读取表时申请排他锁:
如: select * from tbtesta where id = 1 for update;

设置 innodb_lock_wait_timeout
1.设置会话级别:set @@innodb_lock_wait_timeout = 15;
2.设置全局级别:set global innodb_lock_wait_timeout = 15;
3.配置中设置:
innodb_lock_wait_timeout = 15

查看行锁信息:
show status like ‘Innodb_row_lock%’;

相关信息:
Innodb_row_lock_current_waits
innodb表上正在等待的行锁数
Innodb_row_lock_time
获取innodb表上行锁的总时间
Innodb_row_lock_time_avg
获取innodb表上行锁的平均时间,单位毫秒
Innodb_row_lock_time_max
获取innodb表上行锁的最大时间,单位毫秒
Innodb_row_lock_waits
innodb表上操作必须等待表锁的次数

查看表锁相关信息:
show STATUS like ‘Table_locks%’;

Table_locks_immediate
可以立即获得表锁请求的次数
Table_locks_waited
表锁请求等待的次数

相关文章: