mysql临界锁_mysql锁
鎖是什么
鎖是管理不同事務(wù)之間的并發(fā)訪問
理解表鎖和行鎖
在innodb:表鎖是特殊的行鎖,因?yàn)槭前阉械男卸兼i掉的表鎖
鎖定粒度:表鎖 > 行鎖
鎖定效率:表鎖 > 行鎖
沖突概率:表鎖 > 行鎖
并發(fā)性能:表鎖 < 行鎖
鎖類型
行鎖:共享鎖(share locks)和排他鎖(exclusive locks)
共享鎖
對(duì)同一條讀讀共享,讀寫排斥(修改和刪除),類似于ReentrantReadWriteLock
加鎖方式:
select * from users WHERE id=1 LOCK IN SHARE MODE;
例子:
--共享鎖加鎖
1 BEGIN
select * from users WHERE id=1 LOCK IN SHARE MODE;
2其他事務(wù)執(zhí)行
select * from users where id =1;
update users set age=19 where id =1;
因?yàn)樽x寫不能共享
排他鎖
讀讀排他,類似于ReentrantLock
加鎖方式:
Insert,delete,update默認(rèn)加入 for update
Select需要手動(dòng)添加:如select * from users where id =1 for update;
例子:
1 ?set session autocommit = OFF;
update users set age = 23 where id =1;--可以
select * from users where id =1;--可以,行鎖是針對(duì)事務(wù),類似于java的鎖是針對(duì)線程
update users set age = 26 where id =1;
2 --其他事務(wù)執(zhí)行
select * from users where id =1 lock in share mode;--不可以,因?yàn)榕潘?/p>
select * from users where id =1 for update;--不可以,因?yàn)榕潘?/p>
select * from users where id =1;--可以,來自于快照
Innodb行鎖的原理
鎖的是主鍵索引的索引項(xiàng)
通過對(duì)索引的索引項(xiàng)(關(guān)鍵字)加鎖來實(shí)現(xiàn),若檢索時(shí),需要索引條件則使用行鎖,否則則是表鎖(鎖住索引的所有記錄)
例子:
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`age` int(11) NOT NULL,
`phoneNum` varchar(32) NOT NULL,
`lastUpdate` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_eq_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4;
----例子1
set session autocommit = OFF;
update users set lastUpdate=NOW() where phoneNum = '13666666666';--表鎖
rollback;
--其他事務(wù)執(zhí)行
update users set lastUpdate=NOW() where id =2;--不可以,全部的索引項(xiàng)已經(jīng)鎖住了
update users set lastUpdate=NOW() where id =1;--不可以,全部的索引項(xiàng)已經(jīng)鎖住了
-----例子2 主鍵索引
set session autocommit = OFF;
update users set lastUpdate=NOW() where id = 1;--行鎖,鎖id=1的索引
rollback;
--其他查詢執(zhí)行
update users set lastUpdate=NOW() ?where id =2;--可以
update users set lastUpdate=NOW() ?where id =1;--不可以,因?yàn)閕d=1的索引已被鎖住
--------例子3 輔助索引
set session autocommit = OFF;
update users set lastUpdate=NOW() where `name` = 'seven';--行鎖,name是唯一性索引(輔助索引),所對(duì)應(yīng)的是id=1的主鍵索引,索引鎖的是id=1的主鍵索引項(xiàng)
rollback;
--其他查詢執(zhí)行
update users set lastUpdate=NOW() where `name` = 'seven';--不可以,行鎖
update users set lastUpdate=NOW() where id =1;--不可以,行鎖
update users set lastUpdate=NOW() where `name` = 'qingshan';--可以
update users set lastUpdate=NOW() where id =2;;--可以
表鎖
Lock tables xxx read/write
表鎖:若有行鎖或表鎖,則阻塞
意向共享鎖(intention share locks):在事務(wù)操作之前,自動(dòng)添加的,作用是加共享鎖之前,必須先獲取這把鎖
意向排他鎖(intention exclusive locks):在事務(wù)操作之前,自動(dòng)添加的,作用是加排他鎖之前,必須先獲取這把鎖
意義:針對(duì)鎖表功能,鎖表前,先判斷意向鎖是否存在,若存在,則阻塞,若不存在則開始鎖表
例子:
set session autocommit = OFF;
update users set lastUpdate=NOW() where id = 1;--鎖行
rollback;
--其他會(huì)話執(zhí)行
update users set lastUpdate=NOW() where phoneNum = '13777777777';--阻塞
自增鎖(auto-inc locks):
表鎖,類似于通策的主鍵獲取
查看自增模式
show variables like 'innodb_autoinc_lock_mode';
值為1,表示連續(xù)提交,事務(wù)未提交,丟失
如
begin;
insert into users(name , age ,phoneNum ,lastUpdate ) values ('tom2',30,'1344444444',now());--主鍵:10
ROLLBACK;
begin;
insert into users(name , age ,phoneNum ,lastUpdate ) values ('xxx',30,'13444444444',now());--主鍵:11
ROLLBACK;
-- 其他事務(wù)執(zhí)行
insert into users(name , age ,phoneNum ,lastUpdate ) values ('yyy',30,'13444444444',now());--主鍵:12
上面的例子解釋了為什么自增主鍵主鍵不連續(xù)
行鎖的算法
確定鎖的區(qū)間大小:左開右閉,左開右開,只有一條記錄
臨界鎖(next-key locks)
1 前提:命中記錄 + 范圍查找[between and,]
2 特點(diǎn):鎖左開右閉的范圍和下一個(gè)區(qū)間
查詢結(jié)果為7,所在的區(qū)間是(4,7],加下一個(gè)區(qū)間(7,10]
3 間隙的設(shè)定:類似于數(shù)學(xué)的象限,找出臨界點(diǎn),然后開始找到區(qū)間
4 Next-key lock(左開右閉) = gap lock(左開右開) + record lock(一個(gè)點(diǎn),只鎖命中的記錄)
5 為什么鎖下一個(gè)區(qū)間:解決幻讀
例子:
begin;
select * from t2 where id>5 and id<9 for update;
ROLLBACK
-- 其他事務(wù)執(zhí)行
set session autocommit=off;
select * from t2 where id=4 for update;--不阻塞
select * from t2 where id=7 for update;--阻塞
select * from t2 where id=10 for update;--阻塞
INSERT INTO `t2` (`id`, `name`) VALUES (9, '9');--阻塞
間隙鎖(gap locks)
1 前提:不命中記錄 + (范圍查找或等值查找)
2 特點(diǎn):左開右開+查詢范圍最近的第一個(gè)區(qū)間
例子:
begin;
select * from t2 where id >4 and id <6 for update;
--或者
select * from t2 where id =6 for update;
ROLLBACK;
--其他會(huì)話執(zhí)行
INSERT INTO `t2` (`id`, `name`) VALUES (5, '5');
INSERT INTO `t2` (`id`, `name`) VALUES (6, '6');
記錄鎖(record locks)
1 條件:命中記錄 + 等值匹配 + 唯一性索引
2 特點(diǎn):只鎖住這條記錄
例子:
begin;
select * from t2 where id =4 for update;
rollback;
--其他事務(wù)執(zhí)行
select * from t2 where id =7 for update;--不鎖住
select * from t2 where id =4 for update;--鎖住
總結(jié)
以上是生活随笔為你收集整理的mysql临界锁_mysql锁的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 终极解决苹果开发者中心Edit Phon
- 下一篇: linux cmake编译源码,linu