MySQL探秘(五):InnoDB锁的类型和状态查询
鎖是數據庫系統區分于文件系統的一個關鍵特性。數據庫使用鎖來支持對共享資源進行并發訪問,提供數據的完整性和一致性。此外,數據庫事務的隔離性也是通過鎖實現的。InnoDB在此方面一直優于其他數據庫引擎。InnoDB會在行級別上對表數據上鎖,而MyISAM只能在表級別上鎖,二者性能差異可想而知。
InnoDB存儲引擎中的鎖
InnoDB存儲引擎實現了如下兩種標準的行級鎖:
- 共享鎖(S Lock),允許事務讀取一行
- 排他鎖(X Lock),允許事務刪除或更新一行數據
如果一個事務T1已經獲取了行r的共享鎖,那么另外一個事務T2可以立刻獲得行r的共享鎖,因為讀取并不會改變數據,可以進行并發的讀取操作;但若其他的事務T3想要獲取行r的排他鎖,則必須等待事務T1和T2釋放行r上的共享鎖之后才能繼續,因為獲取排他鎖一般是為了改變數據,所以不能同時進行讀取或則其他寫入操作。
XSX不兼容不兼容S不兼容兼容
InnoDB存儲引擎支持多粒度鎖定,這種鎖定允許事務在行級上的鎖和表級上的鎖同時存在。為了支持在不同粒度上進行加鎖操作,InnoDB存儲引擎支持一種稱為意向鎖的鎖方式。意向鎖是將鎖定的對象分為多個層次,意向鎖意味著事務希望在更細粒度上進行加鎖。
InnoDB存儲引擎的意向鎖即為表級別的鎖。設計目的主要是為了在一個事務中揭示下一行將被請求的鎖類型。其支持兩種意向鎖:
- 意向共享鎖(IS Lock),事務想要獲得一張表中某幾行的共享鎖
- 意向排他鎖(IX Lock),事務想要獲得一張表中某幾行的排他鎖
需要注意的是意向鎖是表級別的鎖,它不會和行級的X,S鎖發生沖突。只會和表級的X,S發生沖突。故表級別的意向鎖和表級別的鎖的兼容性如下表所示。
ISIXSXIS兼容兼容兼容不兼容IX兼容兼容不兼容不兼容S兼容不兼容兼容不兼容X不兼容不兼容不兼容不兼容
向一個表添加表級X鎖的時候(執行ALTER TABLE, DROP TABLE, LOCK TABLES等操作),如果沒有意向鎖的話,則需要遍歷所有整個表判斷是否有行鎖的存在,以免發生沖突。如果有了意向鎖,只需要判斷該意向鎖與即將添加的表級鎖是否兼容即可。因為意向鎖的存在代表了,有行級鎖的存在或者即將有行級鎖的存在,因而無需遍歷整個表,即可獲取結果。
如果將上鎖的對象看成一棵樹,那么對最下層的對象上鎖,也就是對最細粒度的對象進行上鎖,那么首先需要對粗粒度的對象上鎖。如上圖所示,如果需要對表1的記錄m行上X鎖,那么需要先對表1加意向IX鎖,然后對記錄m上X鎖。如果其中任何一個部分導致等待,那么該操作需要等待粗粒度鎖的完成。
InnoDB鎖相關狀態查詢
用戶可以使用INFOMATIONSCHEMA庫下的INNODBTRX、INNODBLOCKS和INNODBLOCKWAITS表來監控當前事務并分析可能出現的鎖問題。INNODBTRX的定義如下表所示,其由8個字段組成。
字段名說明trx_idInnoDB存儲引擎內部唯一的事務IDtrx_state當前事務的狀態trx_started事務的開始時間trxrequestlock_id等待事務的鎖ID。如果trx_state的狀態為LOCK WAIT,那么該字段代表當前事務等待之前事務占用的鎖資源IDtrxwaitstarted事務等待的時間trx_weight事務的權重,反映了一個事務修改和鎖住的行數,當發生死鎖需要回滾時,會選擇該數值最小的進行回滾trxmysqlthread_id線程ID,SHOW PROCESSLIST 顯示的結果trx_query事務運行的SQL語句
mysql> SELECT * FROM information_schema.INNODB_TRX\G; ************************************* 1.row ********************************************* trx_id: 7311F4 trx_state: LOCK WAIT trx_started: 2010-01-04 10:49:33 trx_requested_lock_id: 7311F4:96:3:2 trx_wait_started: 2010-01-04 10:49:33 trx_weight: 2 trx_mysql_thread_id: 471719 trx_query: select * from parent lock in share modeINNODBTRX表只能顯示當前運行的InnoDB事務,并不能直接判斷鎖的一些情況。如果需要查看鎖,則還需要訪問表INNODBLOCKS,該表的字段組成如下表所示。
字段名說明lock_id鎖的IDlocktrxid事務的IDlock_mode鎖的模式lock_type鎖的類型,表鎖還是行鎖lock_table要加鎖的表lock_index鎖住的索引lock_space鎖住的space idlock_page事務鎖定頁的數量,若是表鎖,則該值為NULLlock_rec事務鎖定行的數量,如果是表鎖,則該值為NULLlock_data事務鎖住記錄的主鍵值,如果是表鎖,則該值為NULL
mysql> SELECT * FROM information_schema.INNODB_LOCKS\G; *************************************** 1.row ************************************* lock_id: 7311F4:96:3:2 lock_trx_id: 7311F4 lock_mode: S lock_type: RECORD lock_type: 'mytest'.'parent' lock_index: 'PRIMARY' lock_space: 96 lock_page: 3 lock_rec: 2 lock_data: 1通過表INNODBLOCKS查看每張表上鎖的情況后,用戶就可以來判斷由此引發的等待情況。當時當事務量非常大,其中鎖和等待也時常發生,這個時候就不那么容易判斷。但是通過表INNODBLOCKWAITS,可以很直觀的反應當前事務的等待。表INNODBLOCK_WAITS由四個字段組成,如下表所示。
字段名說明requestingtrxid申請鎖資源的事務IDrequestinglockid申請的鎖的IDblockingtrxid阻塞的事務IDblockinglockid阻塞的鎖的ID
mysql> SELECT * FROM information_schema.INNODB_LOCK_WAITS\G; *******************************************1.row************************************ requesting_trx_id: 7311F4 requesting_lock_id: 7311F4:96:3:2 blocking_trx_id: 730FEE blocking_lock_id: 730FEE:96:3:2通過上述的SQL語句,用戶可以清楚直觀地看到哪個事務阻塞了另一個事務,然后使用上述的事務ID和鎖ID,去INNODBTRX和INNDOBLOCKS表中查看更加詳細的信息。
總結
以上是生活随笔為你收集整理的MySQL探秘(五):InnoDB锁的类型和状态查询的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL探秘(四):InnoDB的磁盘
- 下一篇: MySQL探秘(六):InnoDB一致性