MySQL事務問題排查語句

查詢當前事務隔離級別

select @@tx_isolation;

查詢當前執行中事務

select * from information_schema.innodb_trx;

*************************** 1. row ***************************                    

trx_id: 113963                                                            

 trx_state: LOCK WAIT                                                              # 鎖狀態(主要關注)      #事務狀態                

trx_started: 2020-06-13 10:48:48    

 trx_requested_lock_id: 113963:460:3:4          

trx_wait_started:  2020-06-13 10:48:48                

trx_weight: 2        t

rx_mysql_thread_id: 140                                                                       # 執行的線程號 (主要關注)                  

trx_query: update tx1 set c1='heyfffff',c2='heyffffff' where id =3   # 執行語句         (主要關注)        

trx_operation_state: starting index read        

 trx_tables_in_use: 1        

 trx_tables_locked: 1        

  trx_lock_structs: 2      

trx_lock_memory_bytes: 1136                    

 trx_rows_locked: 7                          #事務鎖住的行數        

 trx_rows_modified: 0    trx_concurrency_tickets: 0                          #事務併發票數          

 trx_isolation_level: REPEATABLE READ             # 事務隔離級別        

 trx_unique_checks: 1                                         # 唯一性檢測    

trx_foreign_key_checks: 1                                      # 外鍵檢測

trx_last_foreign_key_error: NULL

 trx_adaptive_hash_latched: 0

 trx_adaptive_hash_timeout: 0          

trx_is_read_only: 0

trx_autocommit_non_locking: 0

*************************** ***************************

查詢執行中進程

命令行狀態下,即非可視化軟件的查詢窗口,navicat可以按F6進入命令行模式

如果有root權限,那麼可以看到所有線程。否則,只能看到登錄的用戶自己的線程,通常只會顯示100條如果想看跟多的可以使用full修飾(show full processlist)

show proecesslist;

+--------+--------------+--------------------+-----------------+-------------+---------+---------------------------------------------------------------+------------------+

| Id     | User         | Host               | db              | Command     | Time    | State                                                         | Info             |

+--------+--------------+--------------------+-----------------+-------------+---------+---------------------------------------------------------------+------------------+

|      9 | root         | xx.42.15.xxx:41200  | ms_communi      | Sleep       |      28 |                                                               | NULL             |

|  74180 | root         | xx.8.62.xxx:45098   | NULL            | Sleep       |      12 |                                                               | NULL             |

|  74187 | root         | xx.8.62.xxx:45136   | NULL            | Binlog Dump | 1053251 | Master has sent all binlog to slave; waiting for more updates | NULL             |

| 113684 | root         | xx.42.15.1xx:54160  | ms_communi      | Sleep       |       4 |                                                               | NULL             |

| 255894 | root         | xxx.8.62.1xx:36216   | NULL            | Sleep       |       4 |                                                               | NULL             |

| 258610 | root         | xxx.8.62.1xx:31268   | ms_memberdb10   | Sleep       |     173 |                                                               | NULL             |

| 258620 | root         | xxx.8.62.1xx:13101   | ms_memberdb11   | Sleep       |     473 |                                                               | NULL             |

| 258713 | root         | xxx.8.62.1xx:60144   | ms_memberdb11   | Sleep       |     473 |                                                               | NULL             |

+--------+--------------+--------------------+-----------------+-------------+---------+---------------------------------------------------------------+------------------+

可以看到當前MySQL執行中的線程

 id       #ID標識,要kill一個語句的時候很有用

use      #當前連接用戶

host     #顯示這個連接從哪個ip的哪個端口上發出

db       #數據庫名

command  #連接狀態,一般是休眠(sleep),查詢(query),連接(connect)

time     #連接持續時間,單位是秒

state    #顯示當前sql語句的狀態

info     #顯示這個sql語句

重點關注 state,command(狀態,命令)

其中ID對應 查詢執行中事務的 trx_mysql_thread_id 字段

這兩個命令可以幫助我們排查異常鎖住的事務,之後可以通過kill命令,殺死線程

殺死線程

kill 74180

74180 爲 show processlist 中的某一行的ID,或爲 trx_mysql_thread_id,用於殺死異常事務的線程

案例

近期有測試報告BUG,偶發性更新某一個會員的數據時,一直報

Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

看到 transaction,Lock,第一反應,事務鎖超時問題。詢問測試持續多久,回覆一直這樣,且只有該會員是這樣,那麼可以判斷出只鎖了某一行。

1.查看當前執行中事務

進入數據庫,查詢當前執行中事務

select * from information_schema.innodb_trx;

 

 

 

可以看到確實有這麼個線程在跑

執行 kill 3576652

詢問測試更新是否恢復正常,回覆說正常,可以確認是事務鎖問題。

2.排查是否是自己的代碼導致Spring事務未釋放。

利用jmeter單會員併發更新,未復現。且方法上加了redis鎖,不應該有爭搶事務鎖的情況出現。

3.詢問其他人是否在事務中批量更新會員信息

有,嘗試調用並且利用DEBUG模式卡住事務不提交,但是由於鎖的行數不對。排除。

4.Navicat誤操作

由於navicat開始事務的按鈕在篩選按鈕附近,十分容易誤操作後忘記點擊提交。

 

詢問測試是否出現上述情況時,是否有手動修改數據,用的軟件是否爲navicat,回覆說是。

自己測試了下,點擊開始事務後,修改數據,不點擊提交。

調用接口更新會員數據,阻塞50秒後(Mysql默認鎖超時時間),返回

Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

執行

select * from information_schema.innodb_trx;

情況復現

回覆測試時,測試剛好在手動改數據,調接口時又觸發了上述錯誤,直接到測試電腦跟前查看,發現navicat的事務按鈕正好爲“提交"顯示,即上述圖片顯示情況。

跟測試解釋具體情況,並在點擊提交後,情況修復,問題解決

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章