mysql的并发处理机制_下篇
2018-06-18 00:26:04来源:未知 阅读 ()
MySQL的并发处理机制,有MVCC及锁机制来处理,上篇简要说明了 MVCC及隔离级别:mysql的并发处理机制_上篇 ,这篇来说说mysql下的锁。
1 Innodb的锁
类型 | 说明 | 场景 |
S | 共享锁 | 针对于RS隔离级别的查询或者添加Lock in share mode的SELECT查询而产生的锁 |
X | 排它锁 | 针对于update、delete、insert操作而产生的锁 |
IS | 意向共享锁 | 表级别的锁,在添加S锁之前对表格添加IS锁 |
IX | 意向排他锁 | 表级别的锁,在添加X锁之前对表格添加IX锁 |
1.1 锁定兼容情况
- 锁粒度小于表级别的锁的兼容情况
- 对于这两行锁的兼容说明如下:
- 假设有一行数据,添加了行锁S锁,那么这个行数据,可以提供给其他事务进行S锁的申请和添加,但是不支持其他事务对这一行进行X锁的申请和添加。比如,事务A,对 pk100 这一行进行了 查询操作并添加了S锁,那么其他事务仍然可以对这一行数据进行查询,但是不能对这行数据进行 UPDATE 跟 DELETE 操作,会处于锁等待情况,直到该事务A结束并释放S锁;
- 假设有一行数据,添加了X锁,那么这个行数据,不允许其他事务对这一行数据进行加锁。比如,事务A,对pk100这一行进行了UPDATE操作,那么其他事务在事务A没有结束之前,都无法对这一行数据申请 S锁。
- 表级的锁兼容情况
- 对于表级别的锁兼容性如下:
- 当一个表格持有S表锁时,不需要其他事务对该表格申请X锁跟IX锁,但是允许申请S跟IS锁。比如,事务A对表格tba全表读,加了S表锁,期间支持其他事务对tba全表读(申请S表锁成功)、支持其他事务对tba行数据查询(申请IS表锁成功),但是不支持对表格全表的修改操作(申请X表锁等待)跟不支持对表格行数据修改操作(申请IX表锁等待);
- 当一个表格持有X表锁时,持有锁期间,不支持其他所有锁的申请;
- 当一个表格持有IS表锁时,允许申请 S表锁、IS表锁、IX表锁,但是不支持X表锁申请。
- 比如,事务A对表格tba 查询了 id = 10(id为主键)这一行数据,这个时候,表格tba持有IS表锁,id = 10 这一行持有 S 行锁,期间,支持其他事务对 tba 全表查询(申请表锁S成功)或者 基于索引查找(申请表锁IS成功)
- 如果需要对行 id = 20 进行数据修改,则会先申请 tba 的表锁 IX(申请成功),然后再申请id=20行锁X (申请成功);如果需要对 id = 10 这一行数据进行修改,则会申请 tba的表锁 IX(表锁申请成功),然后申请 id = 10 的行锁X(申请堵塞,因为 id = 10 正持有S锁);
- 如果需要对表格进行全表修改,需要申请表锁(X锁),这个时候,IS锁的优势来了,当查看表格是否有其他事务在访问操作时,一看表锁IS就知道有其他事务对表格内部某些数据持有S锁,并且还没有释放,那么这个时候,申请X锁就会处于等待状态,而不需要一行一行去查询每一行数据有没有被其他事务持有锁,可以大规模的减少查询 锁申请情况;
- 当一个表格持有IX表锁时,支持申请IS、IX表锁,但是不兼容S、X表锁。
- 比如,事务A对表格 tba 中 id=10 (id为主键)进行进行 数据修改,这个时候,会对表格 tba 先申请一个 IX 表锁(申请成功),然后申请 id =10 的 X 行锁,申请成功,则 事务A 持有 IX 表锁、id=10的X 行锁,此时事务B 查询 id=20的行,申请表锁 IS 成功,申请 id=20的 S 行锁成功;事务C 修改 id=30的行数据,申请表锁 IX 成功,申请 id=30的行锁 X成功;但是,事务D中,对整个表格发起update或者全表SELECT操作,需要申请 X表锁或者S表锁,正常情况下,应该要对表格的每一行数据进行查看,确保每一行数据的行锁情况,但是因为有了意向锁,事务D一看到 tba 持有 了IX锁,则明白,tba 中某些行持有X锁,则会不兼容其他事务对tba 表锁S ,表锁X的申请。
- 为什么要引入意向表锁?
- 在没有意向锁的时候,如果事务T 需要给表格 A 添加 一个S 表锁,那么就意味这这个表格内部的每一行数据,都不能有X锁,才能够申请 S 表锁成功,如果表格数据很多,一行行查找非常浪费加锁时间,这个时候,就出现了表格意向锁,当表格内部某些行发生 UPATE DELETE INSERT操作,则会对表格 加上 一个意向 IX 表锁,这样 事务T在申请 表格A的 S 表锁时,只需要检查 表格 A 是否有 IX表锁,如果有,则意味内部有 部分行数据持有X锁,则直接进入等待情况,如果表格没有 IX表锁,则直接申请S表锁成功,这是一个多么节约加锁时间的操作!
1.2 锁的级别
- Table Lock
- 表锁,如果没有where条件、无可用索引或者获取的行记录过多,则会使用 table full scan,添加表锁
- Record Lock
- 记录锁,如果执行计划使用了索引,则会根据索引的查找情况添加行锁
- Gap Lock
- 在RR、RS隔离级别,发生在索引值之间,在连续的两个索引值之间添加锁,加锁后,这两个索引值之间,无法插入新的索引值,不包含行记录
- Next-Key Lock
- Record Lock 跟Gap Lock的组合,合体成为Next-KEY Lock
1.3 锁与隔离级别(不考虑 lock in shar mode跟for update )
- RU,读未提交记录,不加锁读,正常写锁;
- RC,快照读,无锁;当前读,加 Record Lock
- RR,快照读,无锁;当前读,对读取到的记录加 Record Lock,同时为了确保where条件范围内的数据无变化,会增加Next key lock
- RS,读写均为当前读,不支持快照读。包括select 在内,对读取到的记录加 Record Lock,同时为了确保where条件范围内的数据无变化,会增加Next key lock。
2 锁的申请与释放过程
age
|
2
|
4
|
7
|
9
|
21
|
25
|
id
|
1
|
4
|
5
|
2
|
3
|
6
|
id
|
1
|
2
|
3
|
4
|
5
|
6
|
age
|
2
|
9
|
21
|
4
|
7
|
25
|
name
|
null
|
null
|
null
|
null
|
null
|
null
|
2.1 Read Uncommitted
表格 SQL
|
select * from tbname
where age/id ...
|
update tbname set name=...
where id = 4
|
update tbname set name=...
where age = 21
|
update tbname set name=...
where age between 5 and 15
|
tb_no_index
|
读不加锁,读未提交数据
可能有脏读、不可重复读及幻读
|
当前读,根据主键修改数据
tbname 加意向表锁 IX
id=4 加 行锁 X
|
表格的age列无索引,所以update过程中,全表加X锁
支持semi-constent-read,如果有其他update语句修改其他行不堵塞,但是不支持 select ... for update
|
同左
|
tb_index
|
表格的age列有索引,update过程中
tb_index 加 表格意向锁 IX
age索引上面,age=21 行添加行锁 X
再在主键上,给id=3 这一行数据,添加行数 X
|
表格的age列有索引,update过程涉及age=7,9 两行数据
tb_index 加表格意向锁 IX
age索引上面,age=7,age=9 行添加行锁 X
再在主键上,给id=2,id=5 这一行数据,添加行数 X
|
||
tb_unique_index
|
同上
|
同上
|
2.2 Read Committed
表格
SQL
|
select * from tbname
where age/id ...
|
update tbname set name=...
where id = 4
|
update tbname set name=...
where age = 21
|
update tbname set name=...
where age between 5 and 15
|
tb_no_index
|
快照读,不加锁
读取的数据不一定是最新版本,但是事务内的所有查询读取数据都是同一版本的行数据,不存在脏读、不可重复读及幻读的情况
|
当前读,根据主键修改数据
tbname 加意向表锁 IX
id=4 加 行锁 X
|
表格的age列无索引,所以update过程中,全表加X锁
支持semi-constent-read,如果有其他update语句修改其他行不堵塞,但是不支持 select ... for update
|
同左
|
tb_index
|
表格的age列有索引,update过程中
tb_index 加 表格意向锁 IX
age索引上面,age=21 行添加行锁 X
再在主键上,给id=3 这一行数据,添加行数 X
|
表格的age列有索引,update过程涉及age=7,9 两行数据
tb_index 加表格意向锁 IX
age索引上面,age=7,age=9 行添加行锁 X
再在主键上,给id=2,id=5 这一行数据,添加行数 X
|
||
tb_unique_index
|
同上
|
同上
|
2.3 Read Repeatable
表格 SQL
|
select * from tbname
where age/id ...
|
update tbname set name=...
where id = 4
|
update tbname set name=...
where age = 21
|
update tbname set name=...
where age between 5 and 15
|
tb_no_index
|
快照读,不加锁
读取的数据不一定是最新版本,但是事务内的所有查询读取数据都是同一版本的行数据,不存在脏读、不可重复读及幻读的情况
|
当前读,根据主键修改数据
tbname 加意向表锁 IX
id=4 加 行锁 X
|
表格的age列无索引,所以update过程中
全表加X锁,期间全表堵塞UPDATE\DELETE\INSERT
|
同左
|
tb_index
|
表格的age列有索引,update过程中
tb_index 加 表格意向锁 IX
age索引上面,age=21 行添加行锁 X
再在主键上,给id=3 这一行数据,添加行数 X
你以为结束了!并没有,这里有趣了!
还会添加两个gap lock ((9,2) ,(21,3)),((21,3), (21,25))
这里我们单独拎出小表格来分析。
|
表格的age列有索引,update过程涉及age=7,9 两行数据
tb_index 加表格意向锁 IX
age索引上面,age=7,age=9 行添加行锁 X
再在主键上,给id=2,id=5 这一行数据,添加行数 X
同时会在索引 age的值上添加 3个 gap lock,分别为
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
|
||
tb_unique_index
|
以为跟上面的加锁范围一样,no no no
唯一索引列上 每一个age都是唯一的,也就是age=21只有一个,不会再INSERT一个新的 age =21进来,故在这里不需要加gap lock,加锁情况如下:
tb_index 加 表格意向锁 IX
age=21 行添加行锁 X
age索引上面,age=21 行添加行锁 X
再在主键上,给id=3 这一行数据,添加行数 X
|
表格的age列有索引,update过程涉及age=7,9 两行数据
tb_index 加表格意向锁 IX
age索引上面,age=7,age=9 行添加行锁 X
再在主键上,给id=2,id=5 这一行数据,添加行数 X
同时会在索引 age的值上添加 3个 gap lock,分别为
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
但是,范围查询添加到gap lock在其他情况下跟非唯一索引会有一些差别,可以看下表的例子。
|
2.3.1 RR下的非唯一索引加锁情况
2.3.2 RR下的唯一索引加锁情况
update tbname set name=...
where age between 1 and 7
|
update tbname set name=...
where age between 2 and 7
|
update tbname set name=...
where age between 5 and 10
|
update tbname set name=...
where age between 15 and 50
|
|
tb_index
|
(-∞,2),(2,4),(4,7),(7,9)
|
(-∞,2),(2,4),(4,7),(7,9)
|
(4,7),(7,9),(9,21)
|
(9,21),(21,25),(25,+∞)
|
tb_unique_index
|
(-∞,2),(2,4),(4,7)
|
(2,4),(4,7)
|
(4,7),(7,9),(9,21)
|
(9,21),(21,25),(25,+∞)
|
2.4 Read Serializable
表格 SQL
|
select * from tbname
where age/id ...
|
update tbname set name=...
where id = 4
|
update tbname set name=...
where age = 21
|
update tbname set name=...
where age between 5 and 15
|
tb_no_index
|
不支持快照读,所有SELECT都是当前读,所有SELECT操作都需要加S锁,除主键定值查找\唯一索引定值查找外,其他基于索引或者主键的范围查找都会添加 S GAP LOCK。并发度是四个隔离级别中性能最差的。
|
当前读,根据主键修改数据
tbname 加意向表锁 IX
id=4 加 行锁 X
|
表格的age列无索引,所以update过程中
全表加X锁,期间全表堵塞UPDATE\DELETE\INSERT
|
同左
|
tb_index
|
表格的age列有索引,update过程中
tb_index 加 表格意向锁 IX
age索引上面,age=21 行添加行锁 X
再在主键上,给id=3 这一行数据,添加行数 X
在age索引上 添加两个gap lock ((9,2) ,(21,3)),((21,3), (21,25))
|
表格的age列有索引,update过程涉及age=7,9 两行数据
tb_index 加表格意向锁 IX
age索引上面,age=7,age=9 行添加行锁 X
再在主键上,给id=2,id=5 这一行数据,添加行数 X
同时会在索引 age的值上添加 3个 gap lock,分别为
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
|
||
tb_unique_index
|
唯一索引列上 每一个age都是唯一的,也就是age=21只有一个,不会再INSERT一个新的 age =21进来,故在这里不需要加gap lock,加锁情况如下:
tb_index 加 表格意向锁 IX
age=21 行添加行锁 X
|
表格的age列有索引,update过程涉及age=7,9 两行数据
tb_index 加表格意向锁 IX
age索引上面,age=7,age=9 行添加行锁 X
再在主键上,给id=2,id=5 这一行数据,添加行数 X
同时会在索引 age的值上添加 3个 gap lock,分别为
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
但是,范围查询添加到gap lock在其他情况下跟非唯一索引会有一些差别,可以看下表的例子。
|
表格 SQL
|
select * from tbname
where id=5
|
select * from tbname
where id betwee 5 and 15
|
select * from tbname
where age=21
|
select * from tbname
where age betwee 5 and 9
|
tb_no_index
|
主键定值查找
表格tbname 添加 IS 意向锁
id=5 添加 S锁
|
主键范围查找
表格tbname 添加 IS 意向锁
id=5,id=6 两行数据 添加 S锁
同时添加2个 S GAP LOCK ,分别为 ((5,7),(6,25))跟((6,25),+∞)
|
全表查找
表格 tbname 添加 IS 意向锁
由于全表查找,整个表格 再次添加 S 表锁
|
全表查找
表格 tbname 添加 IS 意向锁
由于全表查找,整个表格 再次添加S 表锁
|
tb_index
|
ix_age索引查找
表格tbname 添加 IS 意向锁
索引上 age = 21 添加 S 行锁
主键上 id=3 添加 S 行锁
同时添加 2个 S GAP LOCK ,分别为 ((9,2) ,(21,3)),((21,3), (21,25))
|
ix_age索引查找
表格tbname 添加 IS 意向锁
age索引上面,age=7,age=9 行添加行锁 S
再在主键上,给id=2,id=5 这一行数据,添加行数 S
同时会在索引 age的值上添加 3个 S gap lock,分别为
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
|
||
tb_unique_index
|
ix_age索引查找
表格tbname 添加 IS 意向锁
索引上 age = 21 添加 S 行锁
主键上 id=3 添加 S 行锁
由于age列唯一,故不需要添加GAP LOCK
|
ix_age索引查找
表格tbname 添加 IS 意向锁
age索引上面,age=7,age=9 行添加行锁 S
再在主键上,给id=2,id=5 这一行数据,添加行数 S
同时会在索引 age的值上添加 2 个 S gap lock,分别为
((4,4),(7,5))、((7,5),(9,2))
|
3 SQL分析
3.1 支持ICP情况
3.2 不支持ICP情况
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- MySQL replace函数怎么替换字符串语句 2020-03-09
- PHP访问MySQL查询超时怎么办 2020-03-09
- mysql登录时闪退 2020-02-27
- MySQL出现1067错误号 2020-02-27
- mysql7.x如何单独安装mysql 2020-02-27
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash