使用数据库时,有时会出现死锁。对于实际应用来说,就是出现系统卡顿。

死锁是指两个或两个以上的事务在执行过程中,因争夺资源而造成的一种互相等待的现象。就是所谓的锁资源请求产生了回路现象,即死循环,此时称系统处于死锁状态或系统产生了死锁。常见的报错信息为“Deadlock found when trying to get lock...”。

上图中,很明显是右侧的四辆汽车造成了死锁。

死锁发生以后,只有部分或完全回滚其中一个事务,才能打破死锁。多数情况下只需要重新执行因死锁回滚的事务即可。下面我们通过一个实例来了解死锁是如何产生的。

例 1
为了方便读者阅读,操作之前我们先查询 tb_student 表的数据和表结构。

mysql> SELECT * FROM tb_student;
+----+------+------+------+------+
| id | name | age  | sex  | num  |
+----+------+------+------+------+
|  1 | 张三 |   31 | 男   |    4 |
|  2 | 李四 |   28 | 男   |    4 |
|  3 | 王五 |   13 | 女   |    4 |
|  4 | 张四 |   13 | 女   |    4 |
|  5 | 王四 |   15 | 男   |    4 |
|  6 | 赵六 |   12 | 女   |    4 |
+----+------+------+------+------+
6 rows in set (0.01 sec)
mysql> DESC tb_student;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(4)      | NO   | PRI | NULL    | auto_increment |
| name  | varchar(25) | NO   |     | NULL    |                |
| age   | int(11)     | YES  | MUL | NULL    |                |
| sex   | char(1)     | YES  |     | NULL    |                |
| num   | int(11)     | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

以下操作需要打开两个会话窗口,即下面所提到的 A窗口和 B窗口。

在 A窗口中执行以下命令:

mysql> BEGIN;
mysql> UPDATE tb_student SET num=5 WHERE age=13;

紧接着在 B窗口中执行以下命令。由于 age 是索引字段,与 A窗口中更新的是不同行的数据,所以这时不会出现锁等待现象。

mysql> BEGIN;
mysql> UPDATE tb_student SET num=8 WHERE age=15;

然后在 A窗口中,执行以下命令,这时就会出现锁等待现象了。

mysql> UPDATE tb_student SET num=10 WHERE age=15;

最后在 B窗口中,执行以下命令,这时会出现相互等待资源的现象,也就是死锁现象。

mysql> UPDATE tb_student SET num=12 WHERE age=13;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

我们可以通过 SHOW ENGINE INNODB STATUS 命令查看死锁的信息,运行结果如下(这里只展示了部分信息):

LATEST DETECTED DEADLOCK
------------------------
2020-08-24 16:22:23 0x3944
*** (1) TRANSACTION:
TRANSACTION 22656, ACTIVE 108 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 5 lock struct(s), heap size 1136, 6 row lock(s), undo log entries 2
MySQL thread id 33, OS thread handle 8808, query id 1689 localhost ::1 root updating
UPDATE tb_student SET num=10 WHERE age=15
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 197 page no 8 n bits 80 index index_age of table `test`.`tb_student` trx id 22656 lock_mode X waiting
Record lock, heap no 5 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 4; hex 8000000f; asc     ;;
1: len 4; hex 80000005; asc     ;;
......

通过以上日志,我们就能确定造成死锁的事务和 SQL 语句。

死锁检测

InnoDB 的并发写操作会触发死锁,同时 InnoDB 也提供了死锁检测机制。通过设置 innodb_deadlock_detect 参数的值来控制是否打开死锁检测。

  • innodb_deadlock_detect = ON:默认值,打开死锁检测。数据库发生死锁时,系统会自动回滚其中的某一个事务,让其它事务可以继续执行。
  • innodb_deadlock_detect = OFF:关闭死锁检测。发生死锁时,系统会用锁等待来处理。

锁等待是指在事务过程中产生的锁,其它事务需要等待上一个事务释放锁,才能占用该资源。如果该事务一直不释放,就需要持续等待下去,直到超过了锁等待时间。当超过锁等待允许的最大时间,就会出现死锁,然后当前事务执行失败,自动执行回滚操作。

MySQL 通过 innodb_lock_wait_timeout 参数控制锁等待的时间,单位是秒。

mysql> SHOW VARIABLES LIKE '%innodb_lock_wait%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 120   |
+--------------------------+-------+
1 row in set, 1 warning (0.02 sec)

在实际应用中,我们要尽量防止锁等待现象的发生,下面介绍几种避免死锁的方法:

  • 如果不同程序会并发存取多个表,或者涉及多行记录时,尽量约定以相同的顺序访问表,这样可以大大降低死锁的发生。
  • 业务中要及时提交或者回滚事务,可减少死锁产生的概率。
  • 在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率。
  • 对于非常容易产生死锁的业务部分,可以尝试使用升级锁粒度,通过表锁定来减少死锁产生的概率(表级锁不会产生死锁)。

10、MySQL锁等待,死锁,死锁检测相关推荐

  1. MySQL - 锁等待及死锁初探

    文章目录 生猛干货 版本信息 MySQL 行锁分析 MySQL死锁演示 排查过程 查看近期死锁日志信息 查询锁等待命令及kill 锁 优化建议 搞定MySQL 生猛干货 带你搞定MySQL实战,轻松对 ...

  2. MySQL锁等待分析【2】

    MySQL锁等待分析[1]中对锁等待的分析是一步一步来的.虽然最后是分析出来了,可是用时是比较长的:理清各个表之间的关系后,得到如下SQL语句,方便以后使用 select block_trx.trx_ ...

  3. mysql 查看锁_SQL-mysql锁等待与死锁

    一 前言 本篇是MYSQL高级进阶篇内容第二篇,学习本篇的基础是知识追寻者之前发布过的文章,尤其是<MYSQL架构入门篇>重中之重: <SQL-你真的了解什么SQL么?> &l ...

  4. mysql锁场景_MySQL死锁系列-常见加锁场景分析

    在上一篇文章<锁的类型以及加锁原理>主要总结了 MySQL 锁的类型和模式以及基本的加锁原理,今天我们就从原理走向实战,分析常见 SQL 语句的加锁场景.了解了这几种场景,相信小伙伴们也能 ...

  5. mysql锁等待问题

    为什么80%的码农都做不了架构师?>>>    相关操作: update a set type=0 where id=1; 执行时提示ERROR 1205 (HY000): Lock ...

  6. MYSQL错误: ERROR 1205: Lock wait timeout exceeded(处理MYSQL锁等待)解决办法

    在运行数据库某一语句的时候(数据量大概有一亿条),运行的特别慢,可能是我自己电脑配置不高,因此想删选一些数据但是运行的时候报1205错误. 原因 有会话执行过DML操作,然后没commit提交,再执行 ...

  7. MySQL - 锁机制初探

    文章目录 生猛干货 Pre 锁的分类 InnoDB 中的锁 行锁 InnoDB 行锁的三种算法实现 Record Lock 锁 Gap Lock 锁 Next-key Lock 锁 表锁 表锁的分类 ...

  8. MySQL锁机制,行锁jingran加在索引上

    锁概述 锁是计算机协调多个进程或线程并发访问某一资源的机制,应该都不陌生.?但在这之前我们先来看看并发控制,理清MVCC多版本并发控制和锁的关系,这也是之前我很迷惑的一个点 并发控制技术 在数据库中, ...

  9. 性能测试瓶颈分析与系统调优(10)mysql数据库性能瓶颈分析调优

    10.1数据库运行机制 数据库--本质就是一个软件系统,这个系统的功能:数据管理[增删改查] 整体结构: 从整体结构角度来看 得出两项优化方案:配置更好的内存:用更好的磁盘硬件,比如:SSD 注意点: ...

最新文章

  1. W3C HTML 工作组联合主席Paul Cotton谈HTML5发展愿景
  2. [原创]Silverlight与PostgreSQL数据库的互操作(CURD完全解析)
  3. Could not find artifact com.sun:tools:jar:1.5.0 解决办法
  4. python中int的意思_python中”int(a[::-1])”的含义是什么?
  5. 爬虫练习:爬豆瓣读书的短评
  6. 拼多多:钟汉良出任“百亿补贴”星推官
  7. 逻辑卷管理和磁盘配额
  8. mongodb之使用explain和hint性能分析和优化
  9. (w10)Prtsc截图键无法正常使用——解决办法
  10. 六行shell脚本实现Android手机自动刷抖音极速版
  11. 大数据和云计算有什么关系?
  12. ios 应用和电脑共享文件夹_无需软件,在ios和Win之间实现高速文件共享
  13. 可以旅游了_原水_新浪博客
  14. 手把青秧插满田,低头便见水中天。心地清净方为道,退步
  15. PHP多人聊天系统,ttltCha​tPHP多人在线聊天系统软件源码 v0.0.12
  16. 关于激光打标机矢量图下载的说明
  17. webpack-es6转es5
  18. vue使用element-ui上传多张图片及回显
  19. 希腊字母输入和公式编辑
  20. 【AnyQ】遇到的问题整理(一)

热门文章

  1. 机器学习-特征工程中的特征选择
  2. JavaScipt30(第三个案例)(主要知识点:css变量)
  3. OpenJudge 1.7 09:密码翻译 题解
  4. appium desktop 1.7 byName不能用,重写
  5. Bellman_Ford算法
  6. 如何一键部署项目代码自动更新
  7. duilib 自带树形控件的认识
  8. MQTT协议通俗讲解
  9. ESP32 各种时钟参数值设置
  10. 渲染管道(3)几何阶段二“坐标转换”