2009-11-06 44 views
6

我想這個問題適用於死鎖,活鎖,或者只是鎖等待超時。如何解決MySQL中的鎖定問題?

我試圖找出查詢引起,導致無法執行另一個查詢的鎖。 Oracle擁有(如果有內存服務的話)一個LOCK表,您可以將它加入到自己的表中,以確定哪些查詢正在鎖定其他查詢。我需要一種方法在MySQL中完成相同的操作。

這種情況是我們有長時間運行的作業偶爾會創建一個更新進度字段的嵌套事務。這樣的話,我們不會失去工作的事務岬,同時保持用戶有關的進展(即完成百分比)。嵌套事務有時會引發鎖超時異常。

這很奇怪,因爲其他工作都不應該從作業表寫入甚至讀取。通過原始SQL日誌篩選證實了這一點。下面是SHOW ENGINE INNODB STATUS交易部分:

------------ 
TRANSACTIONS 
------------ 
Trx id counter 0 479427 
Purge done for trx's n:o < 0 479425 undo n:o < 0 0 
History list length 19 
LIST OF TRANSACTIONS FOR EACH SESSION: 
---TRANSACTION 0 0, not started, OS thread id 3192 
MySQL thread id 31, query id 17417 localhost 127.0.0.1 root 
show engine innodb status 
---TRANSACTION 0 0, not started, OS thread id 3776 
MySQL thread id 29, query id 13062 localhost 127.0.0.1 root 
---TRANSACTION 0 479190, not started, OS thread id 2540 
MySQL thread id 23, query id 16103 localhost 127.0.0.1 testuser 
---TRANSACTION 0 479422, not started, OS thread id 2536 
MySQL thread id 19, query id 17338 localhost 127.0.0.1 testuser 
---TRANSACTION 0 479194, not started, OS thread id 2528 
MySQL thread id 20, query id 16103 localhost 127.0.0.1 testuser 
---TRANSACTION 0 479189, not started, OS thread id 2776 
MySQL thread id 22, query id 16103 localhost 127.0.0.1 testuser 
---TRANSACTION 0 479426, ACTIVE 3 sec, OS thread id 2544 starting index read 
mysql tables in use 1, locked 1 
LOCK WAIT 2 lock struct(s), heap size 320, 1 row lock(s) 
MySQL thread id 18, query id 17414 localhost 127.0.0.1 testuser Updating 
update Job set progress=0.000482780829770491 where id=28 
------- TRX HAS BEEN WAITING 3 SEC FOR THIS LOCK TO BE GRANTED: 
RECORD LOCKS space id 0 page no 23927 n bits 72 index "PRIMARY" of table "test"."job" trx id 0 479426 lock_mode X locks rec but not gap waiting 
Record lock, heap no 5 PHYSICAL RECORD: n_fields 12; compact format; info bits 0 
0: len 8; hex 000000000000001c; asc   ;; 1: len 6; hex 0000000750bf; asc  P ;; 2: len 7; hex 0000005d4d2aeb; asc ]M* ;; 3: len 8; hex 0000000000000005; asc   ;; 4: len 8; hex 0000000000000004; asc   ;; 5: len 8; hex 0000000000000006; asc   ;; 6: len 1; hex 49; asc I;; 7: len 14; hex 800000000000000002749e0e51a6; asc   t Q ;; 8: len 30; hex 3c6d61703e0a20203c656e7472793e0a202020203c737472696e673e7061; asc <map> <entry>  <string>pa;...(truncated); 9: len 8; hex 80001245d33e7e3c; asc E >~<;; 10: SQL NULL; 11: SQL NULL; 

------------------ 
---TRANSACTION 0 479418, ACTIVE 31 sec, OS thread id 960 
14 lock struct(s), heap size 1024, 8 row lock(s), undo log entries 3 
MySQL thread id 21, query id 17404 localhost 127.0.0.1 testuser 

它僅存在兩筆交易出現明確的,那成交479418的14個鎖定一個阻止交易479426.我很想知道是什麼有問題的查詢是。有任何想法嗎?甚至列出14個鎖和導致它們的查詢也會很好。

謝謝!

回答

0

在msql的會話中>嘗試

12.5.5.31。 SHOW PROCESSLIST語法

SHOW [全部] PROCESSLIST

SHOW PROCESSLIST顯示哪些線程正在運行。您也可以從INFORMATION_SCHEMA PROCESSLIST表或中mysqladmin的processlist命令此信息。如果你有PROCESS權限,你可以看到所有的線程。否則,您只能看到自己的線程(即與您正在使用的MySQL帳戶關聯的線程)。如果您不使用FULL關鍵字,則每個語句的前100個字符將顯示在「信息」字段中。

+1

此聲明僅顯示正在運行時正在執行的內容。鑑於我的工作進程每秒執行數百條語句,SQL日誌可能更適合於調試此問題。 – 2009-11-08 16:50:10

0

一個選項是啓用general query log,它將記錄針對mysql運行的所有語句。只要小心它不會佔用你的磁盤空間。

將日誌與innodb狀態輸出中的id進行比較,您會發現罪魁禍首。

+0

是的......這就是我所說的「SQL日誌」的問題。篩選此日誌不會產生對作業表的任何引用(也不會引入表中的外鍵)。我真的很好奇,爲什麼在給定這種情況下更新到這個表的鎖定超時。 – 2009-11-08 17:35:18

+0

嗯,如果他們失敗了,他們可能永遠不會成功。你需要tcpdump(不要忘記-s 1500將整個數據包關閉)。 – 2009-11-08 19:34:45

+0

我不太清楚你的意思。我可以確認Job表的UPDATE語句使它成爲MySQL,因爲它是日誌文件的最後一行。上面的日誌轉儲進一步支持這一點,該日誌轉儲列出了事務479426中的UPDATE。問題是在作業表上存在阻止更新的現有鎖。 – 2009-11-09 15:00:24

4

如果您的查詢等待三秒鐘,那麼這將使他們很容易在slow-query-log中捕獲。另一個Xaprb寫道的建議是use InnoTop。有一個S.O. post on a similar InnoDB lock issue

但是,您可能要查看的代碼,尋找在那裏你正在做一個整體表中選擇的地方。舉例來說,如果你有一個表的工作項目,並要選擇那些懸而未決,做一個

SELECT * FROM queue WHERE status = 'pending' ORDER BY create_date LIMIT 1` 

可能是觸發,將佔據整個表,如果它是在一個臨時文件排序條件交易。將FOR UPDATE添加到選擇可以幫助它更好地獲得鎖。顯然,clustering primary keys can help

在我的環境中,我的查詢連接將報告事務鎖定問題的錯誤,所以我看到如下錯誤:Deadlock found when trying to get lock; try restarting transaction。如果您的查詢實際上失敗,您可能需要檢查警告。 (如果您無法更改應用程序報告查詢失敗的方式,這可能沒有幫助。)

+1

這是非常好的信息...謝謝!在我的具體情況中,外部事務中的查詢都不會很長(0.1秒是最長的),並且奇怪地不會引用發生鎖定超時的Job表。 我們的解決方案涉及Hibernate,因此所有查詢都不是特別複雜(即沒有FOR UPDATE)。 最後,我確實有一個特定的錯誤:「超出鎖定等待超時;嘗試重新啓動事務。」但是,鑑於錯誤發生在嵌套事務中,沒有任何事務重新啓動有幫助。 – 2009-11-10 15:03:46