
文章插图
间隙锁图
死锁
两个事务都需要获得对方持有的排他锁才能继续完成任务,这种互相等待对方释放资源的情况就是死锁 。

文章插图
【大牛总结的MySQL锁优化,写得太好了】死锁图
检测死锁:InnoDB 存储引擎能检测到死锁的循环依赖并立即返回一个错误 。
死锁恢复:死锁发生以后,只有部分或完全回滚其中一个事务,才能打破死锁 。
InnoDB 方法是,将持有最少行级排他锁的事务回滚 。在应用程序设计时必须考虑处理死锁,多数情况下重新执行因死锁回滚的事务即可 。
避免死锁:
- 在事务开始时,如果有记录要修改,先使用 SELECT... FOR UPDATE 语句获取锁,即使这些修改语句是在后面执行 。
- 在事务中,如果要更新记录,直接申请排他锁 。而不是查询时申请共享锁、更新时再申请排他锁 。
简单来说,如果你要更新记录要做两步操作,第一步查询,第二步更新 。就不要第一步上共享锁,第二部上排他锁了,直接在第一步就上排他锁,抢占先机 。
- 如果事务需要锁定多个表,那么尽量按照相同的顺序使用加锁语句,可以降低产生死锁的机会 。
- 通过 SELECT ... LOCK INSHARE MODE(共享锁)获取行的读锁后,如果当前事务再需要对该记录进行更新操作,则很有可能造成死锁 。所以,如果要对行记录进行修改,直接上排他锁 。
- 改变事务隔离级别(事务隔离级别在后面详细说明) 。
在实际开发中无法避免数据被锁的问题,那么我们可以通过哪些手段来查询锁呢?
表级锁可以通过两个变量的查询:
- Table_locks_immediate,产生表级锁的次数 。
- Table_locks_waited,数显表级锁而等待的次数 。
- Innodb_row_lock_current_waits,当前正在等待锁定的数量 。
- Innodb_row_lock_time(重要),从系统启动到现在锁定总时长 。
- Innodb_row_lock_time_avg(重要),每次等待所花平均时间 。
- Innodb_row_lock_time_max,从系统启动到现在等待最长的一次花费时间 。
- Innodb_row_lock_waits(重要),从系统启动到现在总共等待的次数 。
前面讲的死锁是因为并发访问数据库造成 。当多个事务同时访问数据库,做并发操作的时候会发生以下问题 。
脏读(dirty read),一个事务在处理过程中,读取了另外一个事务未提交的数据 。未提交的数据称之为脏数据 。

文章插图
脏读例子
不可重复读(non-repeatable read),在事务范围内,多次查询某条记录,每次得到不同的结果 。
第一个事务中的两次读取数据之间,由于第二个事务的修改,第一个事务两次读到的数据可能不一样 。

文章插图
不可重复读例子
幻读(phantom read),是事务非独立执行时发生的一种现象 。

文章插图

文章插图
幻读的例子
在同一时间点,数据库允许多个并发事务,同时对数据进行读写操作,会造成数据不一致性 。

文章插图
四种隔离级别,解决事务并发问题对照图
隔离性就是用来防止这种数据不一致的 。事务隔离根据级别不同,从低到高包括:
- 读未提交(read uncommitted):它是最低的事务隔离级别,一个事务还没提交时,它做的变更就能被别的事务看到 。有脏读的可能性 。
- 读提交(read committed):保证一个事物提交后才能被另外一个事务读取 。另外一个事务不能读取该事物未提交的数据 。可避免脏读的发生,但是可能会造成不可重复读 。
推荐阅读
- 邱毅在武夷山畅谈两岸共有的中国茶文化
- 神秘的海怪 世界十大海怪未解之谜
- 新开的淘宝店铺怎么做推广引流? 新手淘宝开店怎么引流推广
- 有人发现了外星人造访地球 已发现的外星生物
- 大孔雀蝶是欧洲最什么的蝴蝶 全欧洲最大的蝴蝶是什么蝴蝶
- 北苑贡茶,严苛的生产标准铸造品质好茶
- Linux的/etc/init.d详解
- 花里的蚂蚁怎么处理,蚂蚁对花草有没有害处
- 自媒体人常用的工具大全,15种自媒体工具,提升内容创作效率
- 自己搭建网站的必备常用软件你装了几个?
