MySQL選用可重複讀之前一定要想到的事情(ICP驗證和勘誤)
前文關於ICP最佳化的實驗貌似有誤
http://blog.itpub.net/29254281/viewspace-1398273/
實驗環境
select @@optimizer_switch\G
@@optimizer_switch: index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,matery_materialization_cost_based=on,use_index_extensions=on
1 row in set (0.00 sec)
實驗資料
CREATE TABLE t1 (
id int(11) NOT NULL,
userid varchar(10) DEFAULT NULL,
blogid varchar(10) DEFAULT NULL,
pubtime int(11) DEFAULT NULL,
comment varchar(10) DEFAULT NULL,
PRIMARY KEY (id),
KEY inx_t1_pu (pubtime,userid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO t1 VALUES
(1,'hdc','a',10,NULL),
(4,'yyy','b',3,NULL),
(6,'hdc','c',100,NULL),
(8,'hdc','d',5,'good'),
(10,'hdc','e',1,NULL),
(100,'bbb','f',20,NULL);
commit;
下圖示識的情況實際上有錯誤.
按照前文的說法,啟用ICP二級索引pubtime=3,userid=yyy 和主鍵索引id=4的節點不會被鎖.
首先確定這個SQL會應用ICP
可以看到由Delete改寫的SQL應用了ICP最佳化
執行文中的SQL
delete from t1 where pubtime>1 and pubtime<20 and userid='hdc' and comment is not null;
解析上鎖節點
輔助索引
select conv('000000a',16,10); 10
select conv('0000003',16,10); 3
select conv('0000005',16,10); 5
select conv('0000014',16,10); 20
主鍵索引
select conv('0000001',16,10); 1
select conv('0000004',16,10); 4
select conv('0000008',16,10); 8
select conv('0000064',16,10); 100
實際的情況應該如下圖所示
也就是說,被ICP過濾的資料也會被上鎖.
並且根據MySQL Next-Key Locking,會對間隙鎖右側的資料上鎖,所以輔助索引pubtime=20,userid=bbb的節點和主鍵索引id=100的節點也會被上鎖.
Next Key Locking參考
http://blog.itpub.net/29254281/viewspace-1090160/
糾正錯誤如下
1.ICP不會釋放不符合條件記錄的鎖
按文中的例子,
輔助索引Index key(pubtime > 1 and puptime < 20)選中的節點 3,5,10 會被上鎖.
並且3,5,10產生的4個間隙會被上鎖.
根據Next Key Locking,右側間隙的值會被上鎖.(10,20],也就是說輔助索引pubtime=20,userid=bbb的節點會被上鎖.
最後輔助索引對應的主鍵索引都會被上鎖(id 1,4,8,100)
2.前文圖中間隙鎖的右側邊界節點應該被上鎖,但是圖中沒有標識出來.
http://blog.itpub.net/29254281/viewspace-1398273/
實驗環境
select @@optimizer_switch\G
@@optimizer_switch: index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,mrr=on,mrr_cost_based=on,block_nested_loop=on,batched_key_access=off,matery_materialization_cost_based=on,use_index_extensions=on
1 row in set (0.00 sec)
實驗資料
CREATE TABLE t1 (
id int(11) NOT NULL,
userid varchar(10) DEFAULT NULL,
blogid varchar(10) DEFAULT NULL,
pubtime int(11) DEFAULT NULL,
comment varchar(10) DEFAULT NULL,
PRIMARY KEY (id),
KEY inx_t1_pu (pubtime,userid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO t1 VALUES
(1,'hdc','a',10,NULL),
(4,'yyy','b',3,NULL),
(6,'hdc','c',100,NULL),
(8,'hdc','d',5,'good'),
(10,'hdc','e',1,NULL),
(100,'bbb','f',20,NULL);
commit;
下圖示識的情況實際上有錯誤.
按照前文的說法,啟用ICP二級索引pubtime=3,userid=yyy 和主鍵索引id=4的節點不會被鎖.
首先確定這個SQL會應用ICP
可以看到由Delete改寫的SQL應用了ICP最佳化
執行文中的SQL
delete from t1 where pubtime>1 and pubtime<20 and userid='hdc' and comment is not null;
然後show engine innodb status\G
解析上鎖節點
輔助索引
select conv('000000a',16,10); 10
select conv('0000003',16,10); 3
select conv('0000005',16,10); 5
select conv('0000014',16,10); 20
主鍵索引
select conv('0000001',16,10); 1
select conv('0000004',16,10); 4
select conv('0000008',16,10); 8
select conv('0000064',16,10); 100
實際的情況應該如下圖所示
也就是說,被ICP過濾的資料也會被上鎖.
並且根據MySQL Next-Key Locking,會對間隙鎖右側的資料上鎖,所以輔助索引pubtime=20,userid=bbb的節點和主鍵索引id=100的節點也會被上鎖.
Next Key Locking參考
http://blog.itpub.net/29254281/viewspace-1090160/
糾正錯誤如下
1.ICP不會釋放不符合條件記錄的鎖
按文中的例子,
輔助索引Index key(pubtime > 1 and puptime < 20)選中的節點 3,5,10 會被上鎖.
並且3,5,10產生的4個間隙會被上鎖.
根據Next Key Locking,右側間隙的值會被上鎖.(10,20],也就是說輔助索引pubtime=20,userid=bbb的節點會被上鎖.
最後輔助索引對應的主鍵索引都會被上鎖(id 1,4,8,100)
2.前文圖中間隙鎖的右側邊界節點應該被上鎖,但是圖中沒有標識出來.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-1403331/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL選用可重複讀之前一定要想到的事情MySql
- MySQL選用可重複讀之前一定要想到的事情(無索引加鎖驗證)MySql索引
- MySQL選用可重複讀之前一定要想到的事情(執行計劃影響)MySql
- MySQL在建立索引之前一定要想到的事情MySql索引
- MySQLDump在使用之前一定要想到的事情MySql
- 【MySQL】可重複讀下的幻讀MySql
- Mysql RC/RR隔離原理和區別 不可重複讀和可重複讀MySql
- MySQL 之隔離級別:可重複讀MySql
- MySQL的可重複讀級別能解決幻讀嗎MySql
- Mysql可重複讀(1) —— 快照何時建立MySql
- 為什麼mysql選可重複讀作為預設的隔離級別MySql
- 【MySQL】可重複讀模式下 unique key失效案例MySql模式
- ICP證和EDI證的區別
- 重讀 swift 之一:Optional(可選型)Swift
- MySQL 實戰 | 08 懵逼,可重複讀好像失效了?MySql
- 驗證碼機制之驗證碼重複使用
- MySQL的可插入驗證和客戶端明文驗證外掛介紹MySql客戶端
- MySQL 可重複讀,差點就我背上了一個 P0 事故!MySql
- MySQL 事務隔離實驗-認識:髒讀、不可重複讀、幻讀MySql
- 簡單聊聊mysql的髒讀、不可重複讀MySql
- mysql之許可權驗證MySql
- MySQL MRR和ICP介紹MySql
- 《Oracle核心技術》勘誤——個人閱讀Oracle
- 用jquery驗證使用者名稱是否有效或重複jQuery
- K重交叉驗證和網格搜尋驗證
- MySQL資料庫行去重複和列去重複MySql資料庫
- 【Mysql】資料庫事務,髒讀、幻讀、不可重複讀MySql資料庫
- sql語句中where一定要放在group by 之前SQL
- MySQL 冗餘和重複索引薦MySql索引
- 3分鐘搞清ICP和SP證區別
- 防止重複提交與驗證控制元件配合使用控制元件
- 一文讀懂k8s rbac 許可權驗證K8S
- 髒讀!幻讀!不可重複讀!mysql併發事務引發的問題MySql
- mysql查詢表裡的重複資料方法和刪除重複資料MySql
- 報表/BI工具選型重點注意事項和驗證技巧分享
- 一文詳解髒讀、不可重複讀、幻讀
- 報錯:非介入式客戶端驗證規則中的驗證型別名稱必須唯一。下列驗證型別出現重複客戶端型別
- 髒讀,幻讀,不可重複讀