MySQL锁机制

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: MySQL锁机制

MySQL锁机制


一、锁的粒度

  • 表级锁:
  1. 对整张表加锁
  2. 开销小,加锁快,不会出现死锁
  3. 锁粒度大,发生锁冲突的概率高,并发度低


  • 行级锁:
  1. 对表中某行记录加锁
  2. 开销大,加锁慢,会出现死锁
  3. 锁定粒度最小,发生锁冲突的概率最低,并发度高


二、锁的类型

  1. 排它锁(Exclusive),又称为 X 锁,写锁,写锁和其他锁是不兼容的
  2. 共享锁(Shared),又称为 S 锁,读锁,读锁之间是共享记录的
  • X和S锁之间有以下的关系:

SS可以兼容的,XS、SX、XX之间是互斥的,即读锁之间可以共享,读写和写写之间是不兼容的

  • 加锁效果表现:
  1. 一个事务对数据对象 O 加了 S 锁,只能对 O 进行读取操作,加锁期间其它事务能对O 加 S 锁但不能加 X 锁
  2. 一个事务对数据对象 O 加了 X 锁,可以对 O 进行读取和更新,加锁期间其它事务不能对 O 加任何锁


  • 命令显示加锁:
select ... lock in share mode#强制获取共享锁
select ... for update#获取排它锁


三、InnoDB中的锁

InnoDB的一个特点就是行锁,除了行锁,InnoDB还有表锁和间隔锁

InnoDB通过锁和MVCC(多版本并发控制)实现了事物的隔离性,通过锁解决幻读,通过MVCC实现提交读和可重复读


1、串行化怎么解决幻读

  • 范围条件检索时:
  1. 使用非索引项检索,InnoDB使用表锁:

非索引项没有建立索引树,使用行锁的话需要遍历,效率太慢,所以InnoDB直接用表共享锁,将整个表锁住,如果想进行数据插入删除,需要获取排它锁,这是不能兼容的

0b4f9e796c1218d506b3e3e2080525e1.png

  1. 使用索引项检索,InnoDB会使用行锁+间隙锁:

使用二级索引,通过索引找到主键索引加上行锁,在对应条件的二级索引之间加上间隙锁,防止数据的插入

1f2f5d5ad765cdadadaef7eeef85c8ae.png

  • 等值条件检索时:
  1. 使用非索引项检索,InnoDB同样使用表锁

5363b773aaba347d7986ca72caa9f8ac.png

  1. 使用索引项检索,InnoDB使用行锁:

通过索引记录加上行锁,加上行锁就行,主键和唯一索引的值无法重复


  • 特性总结:
  1. InnoDB行锁是通过给索引上的索引项加锁来实现的,而不是给表的行记录加锁实现的,这就意味着只有通过索引条件检索数据,InnoDB才使用行级锁,否则InnoDB将使用表锁,并且当使用的是二级索引时,同样的根据二级索引找到主键索引上的行记录做加锁
  2. 用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB 会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,做“间隙”加锁,以防止幻读


注意:即使SQL中使用了索引,但是经过MySQL的优化器后,如果认为全表扫描比使用索引效率更高,此时会放弃使用索引,因此也不会使用行锁,而是使用表锁,比如对一些很小的表,MySQL就不会去使用索引


2、意向共享锁和意向排他锁

在绝大部分情况下都应该使用行锁,因为事务和行锁往往是选择InnoDB的理由

  • 但个别情况下也使用表级锁 :
  1. 事务需要更新大部分或全部数据,表又比较大,如果使用默认的行锁,不仅这个事务执行效率低,而且可能造成其他事务长时间等待和锁冲突
  2. 事务涉及多个表,比较复杂,很可能引起死锁,造成大量事务回滚


  • 意向锁的本质:

用来加速获取表的表锁的,意向锁是表级锁,协调表锁和行锁的共存关系

  1. 意向共享锁(IS锁):如果表中某个行共享锁被获取了,那么意向共享锁的状态是被获取的
  2. 意向排他锁(IX锁):如果表中某个行排他锁被获取了,那么意向共享锁的状态是被获取的
  3. 如果要获取表共享锁,那么要检查表的表排他锁和意向排他锁
  4. 如果要获取表排他锁,那么要检查表的表排他锁,表共享锁,意向排他锁和意向共享锁

e5a9be7279dc4f93b3552a87ca824558.png


四、死锁

MyISAM 表锁是 deadlock free 的, 这是因为 MyISAM 总是一次获得所需的全部锁,要么全部满足,要么等待,因此不会出现死锁

但在 InnoDB 中,除单个 SQL 组成的事务外,锁是逐步获得的,即锁的粒度比较小,这就决定了在 InnoDB 中发生死锁是可能的

死锁问题一般都是我们自己的应用造成的,和多线程编程的死锁情况相似,大部分都是由于我们多个线程在获取多个锁资源的时候,获取的顺序不同而导致的死锁问题

因此我们应用在对数据库的多个表做更新的时候,不同的代码段,应对这些表按相同的顺序进行更新操作,以防止锁冲突导致死锁问题


五、锁的优化建议

1.尽量使用较低的隔离级别

2.设计合理的索引并尽量使用索引访问数据,使加锁更加准确,减少锁冲突的机会提高并发能力

3.选择合理的事务大小,小事务发生锁冲突的概率小

4.不同的程序访问一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序存取表中的行,这样可以大大减少死锁的机会

5.尽量用相等条件访问数据,这样可以避免间隙锁对并发插入的影响

6.不要申请超过实际需要的锁级别

7.除非必须,查询时不要显示加锁


六、MVCC多版本并发控制

MVCC是多版本并发控制(Multi-Version Concurrency Control,简称MVCC),是MySQL中基于乐观锁理论实现隔离级别的方式,用于实现已提交读和可重复读隔离级别,也经常称为多版本数据库

MVCC机制会生成一个数据请求时间点的一致性数据快照 (Snapshot), 并用这个快照来提供一定级别 (语句级或事务级) 的一致性读取。从用户的角度来看,好象是数据库可以提供同一数据的多个版本(系统版本号和事务版本号)

MVCC的本质是快照,生成多版本,其底层所依赖的机制是 undo log 回滚日志,保存了事务发生之前的数据的一个版本,用于事务执行时的回滚操作,同时也是实现多版本并发控制(MVCC)下读操作的关键技术

DB_TRX_ID:对记录做修改的事务ID DB_ROLL_PTR:回滚指针,储存旧版本记录数据的地址

9ccb66ef865108b2bfff1784f079d0b4.png

实现已提交读:

可以解决脏读,但是无法解决不可重复读,MVCC对于每一次select都会生成新的快照,而快照中的数据都是经过事物正确commit后的数据

实现可重复读:

解决脏读,不可重复读,MVCC只会在第一次select才会生成当前事务全局性的快照,快照中的数据都是经过事物正确commit后的数据,后续select会沿用第一次的当前读快照

在这种情况下,可重读度在一定程度上解决了幻读,但是如果事物自己update其他事物提交insert数据,是会显示在快照中的

f30024fc2576b5356da1461245b2a029.png

  • MVCC多版本并发控制中,读操作可以分为两类:

1、快照读(snapshot read)

读的是记录的可见版本,不用加锁,如select

mysql> select * from test_dead_lock where id=1 for update;


2、当前读(current read)

读取的是记录的最新版本,并且当前读返回的记录

如insert,delete,update,select…lock in share mode/for update

  • 快照内容读取原则:
  1. 版本未提交无法读取生成快照
  2. 版本已提交,但是在快照创建后提交的,无法读取
  3. 版本已提交,但是在快照创建前提交的,可以读取
  4. 当前事务内自己的更新,可以读到


t,delete,update,select…lock in share mode/for update

  • 快照内容读取原则:
  1. 版本未提交无法读取生成快照
  2. 版本已提交,但是在快照创建后提交的,无法读取
  3. 版本已提交,但是在快照创建前提交的,可以读取
  4. 当前事务内自己的更新,可以读到
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
8月前
|
SQL AliSQL 关系型数据库
MYSQL的全局锁和表锁
本文介绍了MySQL中的锁机制,包括全局锁、表级锁及其应用场景。全局锁通过`Flush tables with read lock (FTWRL)`实现,主要用于全库逻辑备份,但会阻塞更新和结构变更操作。表级锁分为显式表锁(`lock tables`)和元数据锁(MDL),前者用于控制并发访问,后者自动加锁以确保读写正确性。文章还探讨了如何安全地为小表添加字段,建议通过设置DDL等待时间或使用MariaDB/AliSQL的NOWAIT/WAIT功能避免业务阻塞。这些方法有助于在高并发场景下优化数据库性能与安全性。
212 0
|
存储 关系型数据库 MySQL
MySQL MVCC全面解读:掌握并发控制的核心机制
【10月更文挑战第15天】 在数据库管理系统中,MySQL的InnoDB存储引擎采用了一种称为MVCC(Multi-Version Concurrency Control,多版本并发控制)的技术来处理事务的并发访问。MVCC不仅提高了数据库的并发性能,还保证了事务的隔离性。本文将深入探讨MySQL中的MVCC机制,为你在面试中遇到的相关问题提供全面的解答。
928 2
|
缓存 关系型数据库 MySQL
MySQL并发支撑底层Buffer Pool机制详解
【10月更文挑战第18天】在数据库系统中,磁盘IO操作是性能瓶颈之一。为了提高数据访问速度,减少磁盘IO,MySQL引入了缓存机制。其中,Buffer Pool是InnoDB存储引擎中用于缓存磁盘上的数据页和索引页的内存区域。通过缓存频繁访问的数据和索引,Buffer Pool能够显著提高数据库的读写性能。
596 2
|
SQL 关系型数据库 MySQL
MySQL 锁
MySQL里常见的几种锁
238 3
|
canal 消息中间件 关系型数据库
Canal作为一款高效、可靠的数据同步工具,凭借其基于MySQL binlog的增量同步机制,在数据同步领域展现了强大的应用价值
【9月更文挑战第1天】Canal作为一款高效、可靠的数据同步工具,凭借其基于MySQL binlog的增量同步机制,在数据同步领域展现了强大的应用价值
1899 4
|
11月前
|
关系型数据库 MySQL 网络安全
如何排查和解决PHP连接数据库MYSQL失败写锁的问题
通过本文的介绍,您可以系统地了解如何排查和解决PHP连接MySQL数据库失败及写锁问题。通过检查配置、确保服务启动、调整防火墙设置和用户权限,以及识别和解决长时间运行的事务和死锁问题,可以有效地保障应用的稳定运行。
427 25
|
12月前
|
存储 关系型数据库 MySQL
MySQL进阶突击系列(06)MySQL有几种锁?| 别背答案,现场演示一下
本文详细解析了MySQL InnoDB存储引擎的锁机制,涵盖读锁、写锁、意向锁、记录锁、间隙锁和临键锁等8种锁类型。重点探讨了不同锁类型的加锁与释放方式,以及事务并发场景下的实战验证。通过具体示例,展示了在不同情况下锁的行为及其对事务的影响。文章还特别强调了锁的作用范围主要是索引,并解释了锁如何影响数据的读写操作。最后总结了并发事务中加锁规则,帮助读者深入理解MySQL的锁机制。
|
存储 关系型数据库 MySQL
优化 MySQL 的锁机制以提高并发性能
【10月更文挑战第16天】优化 MySQL 锁机制需要综合考虑多个因素,根据具体的应用场景和需求进行针对性的调整。通过不断地优化和改进,可以提高数据库的并发性能,提升系统的整体效率。
752 1
|
关系型数据库 MySQL Java
MySQL数据锁:Record Lock,Gap Lock 和 Next-Key Lock
本文基于 MySQL 8.0.30 版本及 InnoDB 引擎,深入解析三种行锁机制:记录锁(Record Lock)、间隙锁(Gap Lock)和临键锁(Next-key Lock)。记录锁锁定索引记录,确保事务唯一修改;间隙锁锁定索引间的间隙,防止新记录插入;临键锁结合两者,锁定范围并记录自身,有效避免幻读现象。通过具体示例展示了不同锁的作用机制及其在并发控制中的应用。
1302 2
|
存储 关系型数据库 MySQL
MySQL数据库锁:共享锁和独占锁
本文详细介绍了`InnoDB`存储引擎中的两种行级别锁:共享锁(S锁)与排他锁(X锁)。通过具体示例展示了这两种锁的工作机制及其在`InnoDB`与`MyISAM`引擎中的表现差异。文章还提供了锁的兼容性矩阵,帮助读者更好地理解锁之间的互斥关系。最后总结了两种锁的特点及适用场景。适合希望深入了解`MySQL`并发控制机制的读者阅读。
508 1

推荐镜像

更多