mysql鎖之共享鎖vs排他鎖

讀操作 - 共享鎖(InnoDB悲觀鎖)


因?yàn)閙ysql是自動(dòng)提交,但是我們要實(shí)驗(yàn)不讓自動(dòng)提交使用命令set autocommit=0;

共享鎖結(jié)論:
多個(gè)會(huì)話共享同一把鎖。

共享鎖/會(huì)話session 讀操作 寫操作 鎖操作
當(dāng)前session 可以 可以 可以
其他session 可以 阻塞等待操作session的commit(超時(shí)報(bào)錯(cuò)) 可以

加鎖操作:多個(gè)會(huì)話都可以加鎖。
讀操作:多個(gè)會(huì)話共享同一把鎖,每個(gè)會(huì)話都可以去讀數(shù)據(jù)。
寫操作:但是對(duì)于寫數(shù)據(jù),如果一個(gè)會(huì)話寫數(shù)據(jù)了,那么其他會(huì)話都要阻塞等待。

  • 如果當(dāng)前session修改了值,但是還沒有commit提交,那么其他session無法修改表中的所有記錄,只能等待超時(shí)。
  • 其他session可以select查詢數(shù)據(jù),但是查詢的結(jié)果是舊數(shù)據(jù)。

語(yǔ)句:

select XXXXXXX lock in share mode;

實(shí)驗(yàn):

session1 session2
set autocommit =0;
select * from edu_user lock in share mode;
select * from edu_user;
update edu_user set password="456789" where username = "王五";
update edu_user set password="012345" where username = "王五";
等待:1205 - Lock wait timeout exceeded; try restarting transaction
commit;

結(jié)果:

mysql> select password from edu_user where username="王五";
+----------+
| password |
+----------+
| 456789   |
+----------+
1 row in set (0.29 sec)

說明:

  • 當(dāng)前session1獲得共享鎖,session2也可以繼續(xù)添加共享鎖查詢記錄。
  • 但是session2想要寫記錄,將會(huì)處于阻塞狀態(tài)。超過了指定時(shí)間(50s)將報(bào)錯(cuò)。雖然session1寫記錄,但是必須要提交事務(wù),session2才可見。
  • 所以select * from t lock in share mode;一般配合事務(wù)commit命令使用。
  • 查詢共享鎖等待時(shí)間
mysql> show variables like '%innodb_lock_wait_timeout%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 50    |
+--------------------------+-------+
1 row in set (0.00 sec)

讀操作 - 排他鎖(InnoDB悲觀鎖 )


排他鎖結(jié)論:
當(dāng)前事務(wù)加了排他鎖之后,其他事務(wù)什么鎖都不能加。

  • 鎖操作:select * from 表名 where 條件 for update
  • 寫操作:insert / update
  • 讀操作:select * from 表名 where 條件
排他鎖/會(huì)話session 讀操作 寫操作 鎖操作
當(dāng)前session 可以 可以 可以
其他session 可以 阻塞等待(超時(shí)報(bào)錯(cuò)) 阻塞等待(超時(shí)報(bào)錯(cuò))
  • 加鎖操作:如果多個(gè)session的其中一個(gè)session加鎖了,那么其他session只能阻塞。
  • 讀操作:多個(gè)session可以讀。
  • 寫操作:如果存在一個(gè)session加鎖了,那么其他session寫操作都會(huì)阻塞,需要等待已上鎖的session提交commit操作。

語(yǔ)句:

select XXXXXXX for update;

# 自動(dòng):delete / update / insert 默認(rèn)加上排他鎖
# 手動(dòng):select * from table for update

實(shí)驗(yàn):

session1 session2
set autocommit =0;
select * from edu_user for update; set autocommit =0;
成功:select * from edu_user;
阻塞:select * from edu_user for update;
update edu_user set password="456789" where username = "王五";
update edu_user set password = "13579" where username="王五";
等待:1205 - Lock wait timeout exceeded; try restarting transaction
commit;

說明:
當(dāng)前事務(wù)添加了排他鎖后,其他事務(wù)想要添加鎖都將被阻塞。

寫操作 - 排他鎖(InnoDB悲觀鎖 )


delete / update / insert 默認(rèn)會(huì)自動(dòng)加上排他鎖。

update操作:
獲取需要更新的一條記錄的位置,使用排他鎖鎖定該記錄。

session1 session2
set autocommit =0;
update edu_user set username = "李保國(guó)" where id = '5045dfba5f5b4cb5b805c379fc123456'; set autocommit =0;
阻塞:update edu_user set username = "李大嘴" where id = '5045dfba5f5b4cb5b805c379fc123456';
commit; 字段改變?yōu)槔畋?guó)
執(zhí)行:update edu_user set username = "李大嘴" where id = '5045dfba5f5b4cb5b805c379fc123456';
commit; 字段改變?yōu)槔畲笞?/td>

注意:
當(dāng)一個(gè)session在update操作過程中,其他session只能讀操作,只能讀到原來數(shù)據(jù),寫操作,會(huì)阻塞。

delete操作:
獲取刪除記錄的位置,然后使用排他鎖鎖定該記錄。

session1 session2
set autocommit =0;
delete from edu_user where id = '5045dfba5f5b4cb5b805c379fc123456'; set autocommit =0;
阻塞:delete from edu_user where id = '5045dfba5f5b4cb5b805c379fc123456';
commit; 指定記錄刪除
執(zhí)行:delete from edu_user where id = '5045dfba5f5b4cb5b805c379fc123456';
commit;

insert操作:
不需要加鎖,通過隱式鎖來保護(hù)事務(wù)全過程。
insert操作檢查:

  • 情況1:如果記錄之間存在有間隙鎖,那么為了避免幻讀情況,是不能插入記錄。
  • 情況2:如果插入記錄主鍵沖突,也不能插入記錄。
  • 其他情況:插入隱式鎖。
session1 session2
set autocommit =0;
insert into edu_user(id, username, password, role_id) values('1234df4446cb4cb6bc2f639830b12345','張三','123456',3); set autocommit =0;
非阻塞:update edu_user set username= '孫中山' where id = '5045dfba5f5b4cb5b805c379fc538bcb'; 老記錄
阻塞:update edu_user set username= '孫中山' where id = '1234df4446cb4cb6bc2f639830b12345';
commit; 新增一條張三記錄
commit; 更新記錄
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容