MySQL探秘(五):InnoDB锁的类型和状态查询
鎖是數(shù)據(jù)庫系統(tǒng)區(qū)分于文件系統(tǒng)的一個(gè)關(guān)鍵特性。數(shù)據(jù)庫使用鎖來支持對共享資源進(jìn)行并發(fā)訪問,提供數(shù)據(jù)的完整性和一致性。此外,數(shù)據(jù)庫事務(wù)的隔離性也是通過鎖實(shí)現(xiàn)的。InnoDB在此方面一直優(yōu)于其他數(shù)據(jù)庫引擎。InnoDB會(huì)在行級別上對表數(shù)據(jù)上鎖,而MyISAM只能在表級別上鎖,二者性能差異可想而知。
InnoDB存儲(chǔ)引擎中的鎖
InnoDB存儲(chǔ)引擎實(shí)現(xiàn)了如下兩種標(biāo)準(zhǔn)的行級鎖:
- 共享鎖(S Lock),允許事務(wù)讀取一行
- 排他鎖(X Lock),允許事務(wù)刪除或更新一行數(shù)據(jù)
如果一個(gè)事務(wù)T1已經(jīng)獲取了行r的共享鎖,那么另外一個(gè)事務(wù)T2可以立刻獲得行r的共享鎖,因?yàn)樽x取并不會(huì)改變數(shù)據(jù),可以進(jìn)行并發(fā)的讀取操作;但若其他的事務(wù)T3想要獲取行r的排他鎖,則必須等待事務(wù)T1和T2釋放行r上的共享鎖之后才能繼續(xù),因?yàn)楂@取排他鎖一般是為了改變數(shù)據(jù),所以不能同時(shí)進(jìn)行讀取或則其他寫入操作。
XSX不兼容不兼容S不兼容兼容
InnoDB存儲(chǔ)引擎支持多粒度鎖定,這種鎖定允許事務(wù)在行級上的鎖和表級上的鎖同時(shí)存在。為了支持在不同粒度上進(jìn)行加鎖操作,InnoDB存儲(chǔ)引擎支持一種稱為意向鎖的鎖方式。意向鎖是將鎖定的對象分為多個(gè)層次,意向鎖意味著事務(wù)希望在更細(xì)粒度上進(jìn)行加鎖。
InnoDB存儲(chǔ)引擎的意向鎖即為表級別的鎖。設(shè)計(jì)目的主要是為了在一個(gè)事務(wù)中揭示下一行將被請求的鎖類型。其支持兩種意向鎖:
- 意向共享鎖(IS Lock),事務(wù)想要獲得一張表中某幾行的共享鎖
- 意向排他鎖(IX Lock),事務(wù)想要獲得一張表中某幾行的排他鎖
需要注意的是意向鎖是表級別的鎖,它不會(huì)和行級的X,S鎖發(fā)生沖突。只會(huì)和表級的X,S發(fā)生沖突。故表級別的意向鎖和表級別的鎖的兼容性如下表所示。
ISIXSXIS兼容兼容兼容不兼容IX兼容兼容不兼容不兼容S兼容不兼容兼容不兼容X不兼容不兼容不兼容不兼容
向一個(gè)表添加表級X鎖的時(shí)候(執(zhí)行ALTER TABLE, DROP TABLE, LOCK TABLES等操作),如果沒有意向鎖的話,則需要遍歷所有整個(gè)表判斷是否有行鎖的存在,以免發(fā)生沖突。如果有了意向鎖,只需要判斷該意向鎖與即將添加的表級鎖是否兼容即可。因?yàn)橐庀蜴i的存在代表了,有行級鎖的存在或者即將有行級鎖的存在,因而無需遍歷整個(gè)表,即可獲取結(jié)果。
如果將上鎖的對象看成一棵樹,那么對最下層的對象上鎖,也就是對最細(xì)粒度的對象進(jìn)行上鎖,那么首先需要對粗粒度的對象上鎖。如上圖所示,如果需要對表1的記錄m行上X鎖,那么需要先對表1加意向IX鎖,然后對記錄m上X鎖。如果其中任何一個(gè)部分導(dǎo)致等待,那么該操作需要等待粗粒度鎖的完成。
InnoDB鎖相關(guān)狀態(tài)查詢
用戶可以使用INFOMATIONSCHEMA庫下的INNODBTRX、INNODBLOCKS和INNODBLOCKWAITS表來監(jiān)控當(dāng)前事務(wù)并分析可能出現(xiàn)的鎖問題。INNODBTRX的定義如下表所示,其由8個(gè)字段組成。
字段名說明trx_idInnoDB存儲(chǔ)引擎內(nèi)部唯一的事務(wù)IDtrx_state當(dāng)前事務(wù)的狀態(tài)trx_started事務(wù)的開始時(shí)間trxrequestlock_id等待事務(wù)的鎖ID。如果trx_state的狀態(tài)為LOCK WAIT,那么該字段代表當(dāng)前事務(wù)等待之前事務(wù)占用的鎖資源IDtrxwaitstarted事務(wù)等待的時(shí)間trx_weight事務(wù)的權(quán)重,反映了一個(gè)事務(wù)修改和鎖住的行數(shù),當(dāng)發(fā)生死鎖需要回滾時(shí),會(huì)選擇該數(shù)值最小的進(jìn)行回滾trxmysqlthread_id線程ID,SHOW PROCESSLIST 顯示的結(jié)果trx_query事務(wù)運(yùn)行的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表只能顯示當(dāng)前運(yùn)行的InnoDB事務(wù),并不能直接判斷鎖的一些情況。如果需要查看鎖,則還需要訪問表INNODBLOCKS,該表的字段組成如下表所示。
字段名說明lock_id鎖的IDlocktrxid事務(wù)的IDlock_mode鎖的模式lock_type鎖的類型,表鎖還是行鎖lock_table要加鎖的表lock_index鎖住的索引lock_space鎖住的space idlock_page事務(wù)鎖定頁的數(shù)量,若是表鎖,則該值為NULLlock_rec事務(wù)鎖定行的數(shù)量,如果是表鎖,則該值為NULLlock_data事務(wù)鎖住記錄的主鍵值,如果是表鎖,則該值為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查看每張表上鎖的情況后,用戶就可以來判斷由此引發(fā)的等待情況。當(dāng)時(shí)當(dāng)事務(wù)量非常大,其中鎖和等待也時(shí)常發(fā)生,這個(gè)時(shí)候就不那么容易判斷。但是通過表INNODBLOCKWAITS,可以很直觀的反應(yīng)當(dāng)前事務(wù)的等待。表INNODBLOCK_WAITS由四個(gè)字段組成,如下表所示。
字段名說明requestingtrxid申請鎖資源的事務(wù)IDrequestinglockid申請的鎖的IDblockingtrxid阻塞的事務(wù)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語句,用戶可以清楚直觀地看到哪個(gè)事務(wù)阻塞了另一個(gè)事務(wù),然后使用上述的事務(wù)ID和鎖ID,去INNODBTRX和INNDOBLOCKS表中查看更加詳細(xì)的信息。
總結(jié)
以上是生活随笔為你收集整理的MySQL探秘(五):InnoDB锁的类型和状态查询的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL探秘(四):InnoDB的磁盘
- 下一篇: MySQL探秘(六):InnoDB一致性