萬答#1,MySQL中如何查詢某個表上的IS(意向共享)鎖
歡迎來到 GreatSQL社群分享的MySQL技術文章,如有疑問或想學習的內容,可以在下方評論區留言,看到後會進行解答
問題
問題原文是這樣的:
假如在MySQL事務裡,給某個表的一行加了 共享鎖,理論上這個表本身會自動加上意向共享鎖,那麼能不能用 sql 查出這個表加了意向鎖?
回答
答案是肯定的,當然可以執行SQL查詢表上的IS鎖加鎖狀態。
先宣告,我們本次討論的是MySQL裡的InnoDB引擎表,下面討論的內容都是基於這個前提。
在揭曉答案之前,多介紹點InnoDB引擎鎖相關的一些知識吧。主要有以下幾點
-
InnoDB引擎表既支援表級鎖,也支援行級鎖。
-
加表級鎖的方法和MyISAM表是一樣的,執行 LOCK TABLE READ/WRITE 即可。
-
InnoDB表的行鎖是加在索引上的,因此如果沒有合適的索引,是會導致表裡所有記錄都被加上行鎖,其後果等同於表級鎖,但產生的影響比表級鎖可就大多了。因為鎖物件數量大了很多,消耗的記憶體也多很多。
-
加上行鎖時,同時還需要對錶加上相應的意向鎖。例如,想要對一行資料加上共享鎖(S鎖),則相應的要對錶加上意向共享鎖(IS鎖);同樣地,想要對一行資料加上排他鎖(X鎖),則相應的要對錶加上意向排他鎖(IX鎖)。
-
意向鎖是加在聚集索引的根節點上的,因此無論鎖定多少行,只需要加一個意向鎖。
-
下面是幾個鎖之間的相容矩陣
好了,接下來我們來看下怎麼查看錶級IS鎖。其實很簡單,只需要檢視 PFS.data_locks 表就可以了。另一個表 PFS.metadata_locks 表可以檢視MDL鎖的詳情。
查詢結果例如下面這樣:
[[email protected]] [(none)]>select * from performance_schema.data_locks\G *************************** 1. row *************************** ENGINE: INNODB ENGINE_LOCK_ID: 140701134495048:1350:140701396637648 ENGINE_TRANSACTION_ID: 422176111205704 THREAD_ID: 87 EVENT_ID: 95 OBJECT_SCHEMA: yejr OBJECT_NAME: t1 PARTITION_NAME: NULL SUBPARTITION_NAME: NULL INDEX_NAME: NULL OBJECT_INSTANCE_BEGIN: 140701396637648 LOCK_TYPE: TABLE LOCK_MODE: IS LOCK_STATUS: GRANTED LOCK_DATA: NULL *************************** 2. row *************************** ENGINE: INNODB ENGINE_LOCK_ID: 140701134495048:267:4:9:140701409130528 ENGINE_TRANSACTION_ID: 422176111205704 THREAD_ID: 87 EVENT_ID: 95 OBJECT_SCHEMA: yejr OBJECT_NAME: t1 PARTITION_NAME: NULL SUBPARTITION_NAME: NULL INDEX_NAME: PRIMARY OBJECT_INSTANCE_BEGIN: 140701409130528 LOCK_TYPE: RECORD LOCK_MODE: S,REC_NOT_GAP LOCK_STATUS: GRANTED LOCK_DATA: 1
此時我們能看到t1表上共有兩個鎖,一個是表級IS鎖,另一個是c1=1上的共享鎖。
同樣地,我們也可以觀察IX鎖或其他鎖。
- session1執行下面的SQL
[[email protected]] [yejr]>begin; update t1 set c4=rand()*1024 where c1=1;
- session2查詢PFS.data_locks
[[email protected]] [(none)]>select * from performance_schema.data_locks\G
*************************** 1. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140701134495888:1350:140701396639728
ENGINE_TRANSACTION_ID: 104536
THREAD_ID: 89
EVENT_ID: 43
OBJECT_SCHEMA: yejr
OBJECT_NAME: t1
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: NULL
OBJECT_INSTANCE_BEGIN: 140701396639728
LOCK_TYPE: TABLE
LOCK_MODE: IX <-- 這個就是IX鎖了
LOCK_STATUS: GRANTED
LOCK_DATA: NULL
*************************** 2. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140701134495888:267:4:9:140701409135136
ENGINE_TRANSACTION_ID: 104536
THREAD_ID: 89
EVENT_ID: 43
OBJECT_SCHEMA: yejr
OBJECT_NAME: t1
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: PRIMARY
OBJECT_INSTANCE_BEGIN: 140701409135136
LOCK_TYPE: RECORD
LOCK_MODE: X,REC_NOT_GAP
LOCK_STATUS: GRANTED
LOCK_DATA: 1
進一步,我們簡單看下MDL鎖。加共享行鎖:
- session1加一個共享行鎖
[[email protected]] [yejr]>begin; select * from t1 where c1=1 for share;
- session2查詢表上有哪些MDL鎖
[[email protected]] [(none)]>select * from performance_schema.metadata_locks\G
*************************** 1. row ***************************
OBJECT_TYPE: TABLE
OBJECT_SCHEMA: yejr
OBJECT_NAME: t1
COLUMN_NAME: NULL
OBJECT_INSTANCE_BEGIN: 140701215694512
LOCK_TYPE: SHARED_READ <- 共享讀鎖,可以同時加多個共享行鎖
LOCK_DURATION: TRANSACTION
LOCK_STATUS: GRANTED
SOURCE: sql_parse.cc:5761
OWNER_THREAD_ID: 87
OWNER_EVENT_ID: 100
也看下加排他行鎖:
- session1加一個排他行鎖
[[email protected]] [yejr]>begin; update t1 set c4=rand()*1024 where c1=1;
- session2查詢表上有哪些MDL鎖
[[email protected]] [(none)]>select * from performance_schema.metadata_locks\G
*************************** 1. row ***************************
OBJECT_TYPE: TABLE
OBJECT_SCHEMA: yejr
OBJECT_NAME: t1
COLUMN_NAME: NULL
OBJECT_INSTANCE_BEGIN: 140701215694640
LOCK_TYPE: SHARED_WRITE <- 共享寫鎖,可以同時加多個排他行鎖(不同資料行)
LOCK_DURATION: TRANSACTION
LOCK_STATUS: GRANTED
SOURCE: sql_parse.cc:5761
OWNER_THREAD_ID: 89
OWNER_EVENT_ID: 43
好了,方法已有,更多的情形可以自己去玩了 :)
測試環境
Server version: 8.0.23 MySQL Community Server - GPL
上述PFS檢視行鎖、MDL鎖的功能應該是8.0以上就開始支援了。
Enjoy MySQL :)
文章推薦:
技術分享 | MGR最佳實踐(MGR Best Practice)
https://mp.weixin.qq.com/s/66u5K7a9u8GcE2KPn4kCaA
技術分享 | 萬里資料庫MGR Bug修復之路
https://mp.weixin.qq.com/s/IavpeP93haOKVBt7eO8luQ
Macos系統編譯percona及部分函式在Macos系統上運算差異
https://mp.weixin.qq.com/s/jAbwicbRc1nQ0f2cIa_2nQ
技術分享 | 利用systemd管理MySQL單機多例項
https://mp.weixin.qq.com/s/iJjXwd0z1a6isUJtuAAHtQ
產品 | GreatSQL,打造更好的MGR生態
https://mp.weixin.qq.com/s/ByAjPOwHIwEPFtwC5jA28Q
產品 | GreatSQL MGR優化參考
https://mp.weixin.qq.com/s/5mL_ERRIjpdOuONian8_Ow
關於 GreatSQL
GreatSQL是由萬里資料庫維護的MySQL分支,專注於提升MGR可靠性及效能,支援InnoDB並行查詢特性,是適用於金融級應用的MySQL分支版本。
Gitee:
https://gitee.com/GreatSQL/GreatSQL
GitHub:
https://github.com/GreatSQL/GreatSQL
微信&QQ群:
可掃碼新增GreatSQL社群助手微信好友,傳送驗證資訊“加群”加入GreatSQL/MGR交流微信群,亦可直接掃碼加入GreatSQL/MGR交流QQ群。
本文由部落格一文多發平臺 OpenWrite 釋出!