MySQL 锁全解:从行锁到死锁,一文讲透所有面试考点

 更新时间:2026年05月23日 10:45:00   作者:fengxin_rou  
在MySQL中,锁是实现并发控制的一种机制,用于管理对数据库中数据的访问,MySQL支持多种类型的锁,包括表锁和行锁,这篇文章给大家介绍MySQL锁全解:从行锁到死锁个,感兴趣的朋友一起看看吧

在MySQL中,锁是实现并发控制的一种机制,用于管理对数据库中数据的访问。MySQL支持多种类型的锁,包括表锁和行锁。行锁是较为先进的锁机制,因为它允许多个事务同时对数据库中的不同行进行操作,从而提高并发性能。然而,如果不正确管理,即使是行锁也可能导致死锁。

行锁

行锁是MySQL中较为常见的一种锁机制,它允许多个事务对不同的行进行操作,而不会互相干扰。InnoDB存储引擎使用行锁来实现其多版本并发控制(MVCC)。

死锁

死锁是指两个或多个事务在执行过程中,因互相等待对方释放资源而无法继续执行的情况。例如,事务A持有资源B并请求资源C,同时事务B持有资源C并请求资源A。

避免死锁的策略

  • 使用索引‌:确保涉及的所有表都有适当的索引,特别是那些在WHERE子句中使用的列。
  • 锁定顺序‌:在应用中强制一致的锁定顺序。所有事务都应该以相同的顺序请求资源。例如,始终先锁定表A再锁定表B。
    • 超时设置‌:设置InnoDB的innodb_lock_wait_timeout参数,该参数定义了事务等待锁的最长时间。超过这个时间后,事务会自动回滚以避免死锁。
  • 使用乐观锁或悲观锁‌:
    • 悲观锁‌:在事务开始时立即获取所有需要的锁。适用于写操作较多的场景。
    • 乐观锁‌:不使用锁,而是在更新数据前检查版本号或时间戳。适用于读多写少的场景。
  • 检测和解决死锁‌:
    • 使用SHOW ENGINE INNODB STATUS命令查看死锁日志,分析死锁原因。
    • 使用INNODB_TRXINNODB_LOCKSINNODB_LOCK_WAITS表查询当前的事务和锁情况。

mysql里有哪些锁?

在MYSQL里把锁分为三类:全局锁、表锁、行级锁

全局锁:在使用了flush tables with read lock语句之后,全库都会进入只读状态,数据库执行增删改和修改表结构的操作时,都会被阻塞;主要用于在全表进行备份时,防止其他事务修改表的数据

表级锁:

        表锁:使用lock tables语句就会给表上锁,限制其他线程访问这张表,这里对线程有两种限制方式:

1.读锁 lock tables 表名 read

本线程:可读,不能写

其他线程:可读,不能写

2.写锁 lock tables 表名 write

本线程:可读可写

其他线程:读写全都阻塞

        元数据锁:对表上一个MDL锁,如果是对表进行CRUD操作,会对表上MDL读锁,如果是修改表的结构,就会对表上一个MDL写锁,MDL锁的作用是防止线程在操作表时,其他线程影响表的结构和数据

        意向锁当执行插入、更新、删除操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁。意向锁用于确定这个表是否有行级锁

两类意向锁:

  • 意向共享 IS:后续要加共享行锁(S锁)
  • 意向独占 IX:后续要加独占行锁(增删改都会触发、X锁)

行级锁:InnoDB 引擎是支持行级锁的,而 MyISAM 引擎并不支持行级锁。

        记录锁(Record Lock):分为S读锁和X写锁,满足读写互斥和写写互斥

已有锁加 S 锁加 X 锁
S 锁允许阻塞
X 锁阻塞阻塞

        间隙锁(Gap Lock):只存在于可重复读隔离级别,是为了解决可重复读(RR)隔离级别下的幻读现象。

        临键锁(Next-key Lock):记录锁 + 间隙锁合体,会锁定一个范围,并锁定这个范围的数据

InnoDB有哪些锁呢:行级锁、表锁、意向锁

行锁什么时候变表锁?

这里不是有一个升级阈值一样的规定,所谓 “行锁变表锁”,是看起来像锁表,本质是锁了全表所有行 / 大范围间隙,效果等价于表锁。

InnoDB 行锁依托索引生效,无索引 / 索引失效时会全表扫描,行操作就会查询全表,然后给所有行加锁效果等价于表锁

临键锁怎么解决幻读?

因为临建锁 = 间隙锁 + 记录锁,利用这两个锁的机制就可以大幅度的减少幻读的发生

  • 锁住查到的真实数据行(记录锁) 不让别人修改已有数据
  • 锁住数据前后的空白间隙(间隙锁) 区间内无法插入新记录
  • 范围查询会锁定一整个左开右闭区间 别的事务插不进区间空位,自然不会凭空多出数据,大幅规避幻读

什么是死锁?产生条件、怎么排查和避免死锁?

死锁定义:

两个事务互相持有对方的锁,并且自身不会主动释放锁,互相陷入等待的循环就是锁

产生条件:

  1. 互斥性:一把锁只有一个事务可以拿到
  2. 请求并保持:持有锁的同时去请求另一把锁
  3. 不可剥夺:锁不能被抢走,只能主动释放
  4. 循环等待:A等B的锁,B等A的锁

MySQL 排查死锁

查看最近死锁日志

show engine innodb status;

日志里看:阻塞 SQL、持有锁、等待锁、事务执行顺序,定位冲突语句

避免死锁:

  1. 统一访问顺序 :所有事务按相同顺序操作表、操作行,杜绝循环等待。
  2. 缩小事务范围 :事务尽量短小,尽早提交,减少锁持有时间。
  3. 合理使用索引 :保证更新语句走索引,锁定行数越少,锁冲突越少。
  4. 避免事务内等待交互 :不要事务中途等待用户操作、接口调用,防止长时间占锁。

总结:

主要是了解了mysql里面所有的锁的定义,行锁与表锁并不是字面意思上的转换,而是效果上在全盘扫描时实现了锁全表的现象,临键锁解决幻读,从临键锁的组成来分为锁数据(记录锁)和锁数据前后的空白间隙(间隙锁),以及死锁的相关知识。

到此这篇关于MySQL 锁全解:从行锁到死锁,一文讲透所有面试考点的文章就介绍到这了,更多相关mysql行锁到死锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SQL使用聚集函数实现对数据汇总

    SQL使用聚集函数实现对数据汇总

    这篇文章主要介绍了SQL使用聚集函数实现对数据汇总,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-09-09
  • Mysql连接本地报错:1130-host ... is not allowed to connect to this MySQL server解决

    Mysql连接本地报错:1130-host ... is not allowed to connect t

    这篇文章主要给大家介绍了关于Mysql连接本地报错:1130-host ... is not allowed to connect to this MySQL server的解决方法,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-03-03
  • MySQL count(*),count(id),count(1),count(字段)区别

    MySQL count(*),count(id),count(1),count(字段)区别

    本文主要介绍了MySQL count(*),count(id),count(1),count(字段)区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • mysql仿asp的数据库操作类

    mysql仿asp的数据库操作类

    使用说明: 该类完全按照ADO的习惯书写的,用过ASP的人都觉得ASP连接数据库比PHP好用(这是我的感觉), 但PHP得一个一个API地写,挺累,该类做了完全的封装 创建类的实例时可以指定一个数据库表和选择的数据库,如:new MySQLDB("table","database");
    2008-04-04
  • mysql误删数据后快速恢复的办法推荐

    mysql误删数据后快速恢复的办法推荐

    手抖不小心把表里的数据删除或修改错误怎么办?该如何快速恢复呢?遇到这样的问题怎么办?下面这篇文章主要给大家介绍了关于mysql误删数据后快速恢复的相关资料,需要的朋友可以参考下
    2023-02-02
  • MySQL字符集utf8修改为utf8mb4的方法步骤

    MySQL字符集utf8修改为utf8mb4的方法步骤

    这篇文章主要给大家介绍了关于MySQL字符集utf8修改为utf8mb4的方法步骤,文中通过示例代码介绍的非常详细,对大家学习或者使用MySQL具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-07-07
  • 简单了解mysql存储字段类型查询效率

    简单了解mysql存储字段类型查询效率

    这篇文章主要介绍了简单了解mysql存储字段类型查询效率,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • Mysql实现主从配置和多主多从配置

    Mysql实现主从配置和多主多从配置

    大型网站为了软解大量的并发访问,除了在网站实现分布式负载均衡,远远不够。必然会想到假设服务器群,来分担主数据库的压力。今天总结一下利用MySQL主从配置,减轻数据库压力
    2021-06-06
  • MySql insert插入操作的3个小技巧分享

    MySql insert插入操作的3个小技巧分享

    这篇文章主要介绍了MySql insert插入操作的3个小技巧分享,本文讲解了插入的数据来源自其他表、插入时排除(忽略)重复记录、插入时遇到重复记录做更新操作三个小技巧,需要的朋友可以参考下
    2015-03-03
  • MySQL中使用自定义变量 编写偷懒的UNION示例

    MySQL中使用自定义变量 编写偷懒的UNION示例

    以下是对MySQL中使用自定义变量,编写一个UNION的示例进行了详细的介绍,需要的朋友可以过来参考下
    2013-07-07

最新评论