
MySQL进阶-锁

1. 锁的分类
全局锁
锁住整个库 用来数据备份
表锁
MySQL 里面表级别的锁有两种:一种是表锁,一种是元数据锁(meta data lock,MDL)。
- 表锁
举个例子, 如果在某个线程 A 中执行 lock tables t1 read, t2 write; 这个语句,则其他线程写 t1、读写 t2 的语句都会被阻塞。同时,线程 A 在执行 unlock tables 之前,也只能执行读 t1、读写 t2 的操作。连写 t1 都不允许,自然也不能访问其他表。
- 元数据锁 表结构
读锁之间不互斥,因此你可以有多个线程同时对一张表增删改查。
读写锁之间、写锁之间是互斥的,用来保证变更表结构操作的安全性。因此,如果有两个线程要同时给一个表加字段,其中一个要等另一个执行完才能开始执行。 - 意向锁
意向锁存在的意义在于,使得行锁和表锁能够共存。
由数据库引擎控制,当需要对数据行加s锁x锁时执行操作时,INNODB首先会获取所在表的意向锁,若能获得,则可以加s锁x锁。
避免了逐行检查是否加了行级锁1
2
3
4--设置共享锁:
select * from user where id = 1 LOCK IN SHARE MODE;
--设置排他锁:
select * from user where id = 1 FOR UPDATE;
行锁
行级锁是 MySQL 中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少
INnoDB的行锁是针对索引加的,若不通过索引检索数据,则会对所有记录加锁
- 间隙锁
间隙锁,锁定一个范围,但不包含本身,如(1,5
间隙锁是存储引擎为了防止幻读,而引入的锁机制。间隙锁之间是互不冲突的,因此可以有多个 - 临键锁 (next-key lock)
临键锁,锁定一个范围,并且包含本身
2.mysql锁在4种事务隔离级别里的应用
事务的四种隔离级别有:
- 读未提交(Read Uncommitted)
此时select语句不加任何锁。此时并发最高,但会产生脏读。
- 读提交(Read Committed, RC)
普通select语句是快照读
update语句、delete语句、显示加锁的select语句(select … in share mode 或者 select … for update) 等,除了在外键约束检查和重复键检查时会封锁区间,其他情况都只使用记录锁;
- 可重复读(Repeated Read, RR)
普通select语句也是快照读
update语句、delete语句、显示加锁的select语句(select … in share mode 或者 select … for update)则要分情况:
1. 在唯一索引上使用唯一的查询条件,则使用记录锁。如: select * from user where id = 1;其中id建立了唯一索引
2. 在唯一索引上使用 范围查询条件,则使用间隙锁与临键锁。如: select * from user where id >20;
- 串行化(Serializable)
此时所有select语句都会被隐式加锁:select … in share mode.
3.快照读、当前读
要理解前面四种隔离级别的加锁方式,对于MVCC、快照读、当前读 都是必须要理解的。
MVCC并发控制中,读操作可以分成两类:快照读 (snapshot read)与当前读 (current read)。
快照读,读取的是记录的可见版本 (有可能是历史版本),不用加锁。
当前读,读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。
在 RC 级别下,对于快照数据,一致性非锁定读总是读取被锁定行的最新一份快照数据。
在 RR 级别下,对于快照数据,一致性非锁定读总是读取本事务开始时的行数据版本。
什么是多版本并发控制(MVCC:multi-version concurrency control )
MVCC定义:多版并发控制系统。可认为是行级锁的一个变种,它能够避免更多情况下的加锁操作。
作用:避免一些加锁操作,提升并发性能。
实现:通过在每行记录的后面保存行的创建时间和过期时间或删除时间(它们是隐藏的),这两个时间实际都是系统的版本号。每开始一个新的事务,版本号都会自动增加。
具体原理
1.select:innoBD查询时会检查以下两个条件:一个是数据行的版本号早于当前事务的版本号;另一个是行的删除版本号,要么没有,要么大于当前事务的版本号。
2.insert/delete:innoDB将当前的系统版本号作为新插入(删除)的数据行的版本号。
3.update:先新插入一行数据,并将当前系统版本号作为行的版本号,同时将当前系统版本号作为原来行的删除版本号。更新主键时,聚集索引和普通索引都会产生两个版本;而更新非主键时,只要普通索引会产生两个版本。
- Title: MySQL进阶-锁
- Author: Jason
- Created at : 2023-09-08 16:09:12
- Updated at : 2023-09-10 16:00:53
- Link: https://xxxijason1201.github.io/2023/09/08/MySQL/锁/
- License: This work is licensed under CC BY-NC-SA 4.0.