最近對insert的鎖操作比較費解,所以自己動手,一看究竟。主要是通過一下三個sql來看一下執行中的sql的到底使用了什么鎖。
select * from information_schema.INNODB_TRX\G; //記錄當前正在執行的事務,以及事務的一些狀態
select * from information_schema.INNODB_LOCKS\G; //包含了InnoDB事務鎖的具體情況,包括事務正在申請加的鎖和事務加上的鎖。
select * from information_schema.INNODB_LOCK_WAITS; //包含了blocked的事務的鎖等待的狀態
mysql的版本:5.6.25-73.1-log 使用了innodb,隔離級別是 REPEATABLE-READ
首先看下表結構: 表中有唯一鍵
分別在倆個事務中執行同樣的insert操作:
insert into room_poi_cut_result (poi_id,poi_orgunit_id,old_bd,new_bd,cut_reason,is_execute) values(12345,22,12,12,0,0);
首先看下 INNODB_TRX 表的數據:可以看到 事務10722584462處於執行狀態,事務10722584486處於阻塞狀態
然后再看下鎖的狀態:可以看到,事務10722584462和事務10722584486都是在獲取行鎖,一個是S鎖,一個是X鎖
最后我們看下 INNODB_LOCK_WAITS 這個表中的數據:可以看到事務10722584486正在被阻塞在10722584486:29178:10:638 這個鎖上,而這個鎖的持有者是事務10722584462
所以,這里可以得到結論,首先會在唯一鍵加上行鎖,其次insert語句會有一個鎖升級的過程,從S鎖升級到X鎖。
接下來做第二個實驗,在inser中加入 on update語句。
分別在倆個事務中執行同樣的insert操作:
insert into room_poi_cut_result (poi_id,poi_orgunit_id,old_bd,new_bd,cut_reason,is_execute) values(12345,22,12,12,0,0) on duplicate key update poi_id=12345;
然后再看下INNODB_TRX,INNODB_LOCKS,INNODB_LOCK_WAITS 這三個表的數據:
結論,首先會在唯一鍵加上行鎖,其次和第一次實驗不同的是,直接是在唯一鍵上加X鎖。
接下來做第三個實驗,把表的唯一鍵去掉,然后執行insert操作:
表結構:
然后在倆個事務中執行以下insert語句:
insert into room_poi_cut_result2 (poi_id,poi_orgunit_id,old_bd,new_bd,cut_reason,is_execute) values(12345,22,12,12,0,0);