MySQL - 深入理解锁机制和实战场景

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: MySQL - 深入理解锁机制和实战场景

MySQL 为了解决事务并发、数据安全的问题,提供并使用了锁机制,下面先看一张图,了解一下 MySQL 有哪些锁:

接下来,一起深入学习 MySQL 的锁机制。

1. 锁的分类

1.1 行级锁

行级锁应用在 InnoDB 存储引擎中,每次锁住一行数据。

  • 优点:锁定粒度小,发生锁冲突的概率最低,并发度最高。
  • 缺点:开销大,加锁慢;会出现死锁。

1.2 页级锁

页级锁应用在 DBD 存储引擎中,每次锁住一页数据 - 16KB左右。

  • 特点:开销和加锁时间介于表级和行级之间;会出现死锁,锁定力度介于表锁和行锁之间,并发度一般。

1.3 表级锁

表级锁应用在 MyISAM、InnoDB、BDB 等存储引擎中,每次操作锁住整张表。

  • 优点:开销小,加锁快;不会出现死锁。
  • 缺点:锁定粒度大,发生锁冲突的概率最高,并发度最低。

2. 行级锁的分类

接下来进行行级锁的详解,行级锁主要分为以下7类:共享/排他锁、意向锁、记录锁、间隙锁、临建锁、插入意向锁、自增锁。

2.1 共享锁、排他锁

共享锁(S锁):共享锁(Share Locks,简记为S锁)又被称为读锁,其他事务可以并发读取数据,但任何事务都不能获取数据上的排他锁(只能加共享锁,不能加排他锁),直到已释放所有共享锁。

若事务 T 对数据对象 A 加上 S锁,则事务 T 只能读 A;其他事务只能再对 A 加 S锁,而不能加 X锁,直到T释放A上的S锁。这就保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。

select ... lock in share mode;

排他锁(X锁):排它锁((Exclusive lock,简记为X锁))又称为写锁,不能允许读,也不能允许写,排他锁不能与其他锁一起使用。

若事务T对数据对象 A 加上 X锁,则只允许 T 读取和修改 A,其它任何事务都不能再对 A 加任何类型的锁,直到 T 释放 A 上的锁。它防止任何其它事务获取资源上的锁,直到在事务的末尾将资源上的原始锁释放为止。在更新操作(INSERT、UPDATE 或 DELETE)过程中始终应用排它锁。

select ... for update;

MySQL 中,updatedeleteinsertalter 这些写的操作默认都会加上排他锁。select 默认不会加任何锁类型。一旦写数据的任务没有完成,数据是不能被其他任务读取的,这对并发操作有较大的影响。

2.2 意向锁

InnoDB 为了支持多粒度的锁,即允许行级锁和表级锁共存,而引入意向锁。意向锁是指未来的某个时刻,事务可能要加共享/排他锁,先提前声明一个意向。这样如果有人尝试对全表进行修改,就不需要判断表中的数据是否被加锁了,只需要通过等待意向互斥锁被释放就行了。

意向共享锁(IS):事务想要在获得表中某些记录的共享锁,需要在表上先加意向共享锁。

意向互斥锁(IX):事务想要在获得表中某些记录的互斥锁,需要在表上先加意向互斥锁。

意向锁其实不会阻塞全表扫描之外的任何请求,它们的主要目的是为了表示是否有人请求锁定表中的某一行数据。

2.3 记录锁(RS)

单个行记录上的锁。记录锁总是会锁住索引记录,如果 InnoDB 存储引擎表

在建立的时候没有设置任何一个索引,那么InnoDB存储引擎会使用隐式的主键来进行锁定。

2.4 间隙锁(GR)

间隙锁锁住记录中的间隔,即范围查询的记录。

select * From user where id between 1 and 10 for update;

这个脚本会锁住 1 到 10 的数据,以防止其他事务修改该区间的记录;

间隙锁的主要目的,就是为了防止其他事务在间隔中插入数据,以导致“不可重复读”。如果把事务的隔离级别降级为读提交(Read Committed, RC),间隙锁则会自动失效。

2.5 临建锁(next-key Locks)

临建锁是记录锁和间隙锁的组合,锁的范围既包含记录又包含索引区间。默认情况下,InnoDB使用临建锁来锁定记录。但当查询的索引含有唯一属性的时候,临建锁会进行优化,将其降级为记录锁,即仅锁住索引本身,不是范围。

临键锁的主要目的,也是为了避免幻读(Phantom Read)。如果把事务的隔离级别降级为 RC,临键锁则也会失效。

2.6 插入意向锁(insert intention locks)

对已有数据行的修改和删除,必须加互斥锁,对于数据的插入,加插入意向锁。是专门针对于 insert 操作的。

2.7 自增锁(auto-inc locks)

是一种特殊的表级别的锁,专门针对事务插入 auto-increment 类型的列。最简单的情况,如果一个事务正在往表中插入记录,所有其他事务的插入必须等待,以便第一个事务插入的行,是连续的主键值。

3. 悲观锁和乐观锁

3.1 悲观锁

悲观的假定大概率会发生并发更新冲突,访问、处理数据前就加排他锁,在整个数据处理过程中锁定数据,事务提交或回滚后才释放锁。

  • 优点:

悲观并发控制实际上是“先取锁再访问”的保守策略,为数据处理的安全提供了保证。

  • 缺点:

(1)在效率方面,处理加锁的机制会让数据库产生额外的开销,还有增加产生死锁的机会;

(2)在只读型事务处理中由于不会产生冲突,也没必要使用锁,这样做只能增加系统负载;还有会降低了并行性,一个事务如果锁定了某行数据,其他事务就必须等待该事务处理完才可以处理那行数

案例:

  1. 假定 MySQL 有客户端A 与客户端B 同时开启事务
  2. 在 A 里面进行查询数据:select * from tab where id = 1 for update;
  3. 由于 B端 还没有提交事务,A端 则会在执行这条 SQL 语句时锁住(卡住不动),B端 结束了事务,A端 才会继续执行 SQL。

3.2 乐观锁

乐观的假定大概率不会发生并发更新冲突,访问、处理数据的过程中不加锁,只在更新数据时根据版本号时间戳判断是否有冲突,有则处理,无责提交事务。

如果系统并发量非常大,悲观锁会带来非常大的性能问题,选择使用乐观锁,现在大部分应用属于乐观锁

下单案例:

  1. 查询商品信息
select (quantity,version) from products where id=1;
  1. 根据商品信息生成订单
insert into orders ... 
insert into items ...
  1. 修改商品库存
update products set quantity = quantity - 1,version = version +  1 where id = 1 and version = #{version};

除了自己手动实现乐观锁之外,许多数据库访问框架也封装了乐观锁的实现,比如 hibernate 框架。MyBatis 框架大家可以使用 OptimisticLocker 插件来扩展。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
28天前
|
缓存 关系型数据库 MySQL
MySQL索引策略与查询性能调优实战
在实际应用中,需要根据具体的业务需求和查询模式,综合运用索引策略和查询性能调优方法,不断地测试和优化,以提高MySQL数据库的查询性能。
|
1月前
|
存储 关系型数据库 MySQL
MySQL MVCC全面解读:掌握并发控制的核心机制
【10月更文挑战第15天】 在数据库管理系统中,MySQL的InnoDB存储引擎采用了一种称为MVCC(Multi-Version Concurrency Control,多版本并发控制)的技术来处理事务的并发访问。MVCC不仅提高了数据库的并发性能,还保证了事务的隔离性。本文将深入探讨MySQL中的MVCC机制,为你在面试中遇到的相关问题提供全面的解答。
170 2
|
2月前
|
缓存 关系型数据库 MySQL
MySQL并发支撑底层Buffer Pool机制详解
【10月更文挑战第18天】在数据库系统中,磁盘IO操作是性能瓶颈之一。为了提高数据访问速度,减少磁盘IO,MySQL引入了缓存机制。其中,Buffer Pool是InnoDB存储引擎中用于缓存磁盘上的数据页和索引页的内存区域。通过缓存频繁访问的数据和索引,Buffer Pool能够显著提高数据库的读写性能。
129 2
|
2月前
|
存储 关系型数据库 MySQL
MySQL在企业内部应用场景有哪些
【10月更文挑战第17天】MySQL在企业内部应用场景有哪些
71 0
|
2月前
|
存储 关系型数据库 MySQL
介绍一下MySQL的一些应用场景
【10月更文挑战第17天】介绍一下MySQL的一些应用场景
275 0
|
1月前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
218 1
|
2月前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:优化百万数据查询的实战经验
【10月更文挑战第13天】 在处理大规模数据集时,传统的关系型数据库如MySQL可能会遇到性能瓶颈。为了提升数据处理的效率,我们可以结合使用MySQL和Redis,利用两者的优势来优化数据查询。本文将分享一次实战经验,探讨如何通过MySQL与Redis的协同工作来优化百万级数据统计。
79 5
|
2月前
|
存储 关系型数据库 MySQL
优化 MySQL 的锁机制以提高并发性能
【10月更文挑战第16天】优化 MySQL 锁机制需要综合考虑多个因素,根据具体的应用场景和需求进行针对性的调整。通过不断地优化和改进,可以提高数据库的并发性能,提升系统的整体效率。
113 1
|
1月前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
86 0
|
2月前
|
存储 关系型数据库 MySQL
MySQL锁,锁的到底是什么?
【10月更文挑战第16天】MySQL 锁锁定的是与数据和资源相关的对象,其目的是为了保证数据的一致性、避免冲突,并在并发环境下合理协调事务或操作的执行。理解锁的对象和意义对于优化数据库性能、处理并发问题至关重要。
78 0