您好,登錄后才能下訂單哦!
MySQL 行鎖超如何排查,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
#### 20191219 10:10:10,234 | com.alibaba.druid.filter.logging.Log4jFilter.statementLogError(Log4jFilter.java:152) | ERROR | {conn-10593, pstmt-38675} execute error. update xxx set xxx = ? , xxx = ? where RowGuid = ? com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
之前在 [如何有效排查解決 MySQL 行鎖等待超時問題] 文章中介紹了如何監控解決行鎖超時報錯,當時介紹的監控方案主要是以 shell 腳本 + general_log 來捕獲行鎖等待信息,后來感覺比較麻煩,因此優化后改成用 Event + Procedure 的方法定時在 MySQl 內執行,將行鎖等待信息記錄到日志表中,并且加入了 pfs 表中的事務上下文信息,這樣可以省去登陸服務器執行腳本與分析 general_log 的過程,更加便捷。
因為用到了 Event 和 performance_schema 下的系統表,所以需要打開兩者的配置,pfs 使用默認監控項就可以,這里主要使用到的是 events_statements_history 表,默認會保留會話 10 條 SQL。
performance_schema = on event_scheduler = 1
目前該方法僅在 MySQL 5.7 版本使用過,MySQL 8.0 未測試。
create database `innodb_monitor`;
create database `innodb_monitor`;
2.2 創建存儲過程
use innodb_monitor; delimiter ;; CREATE PROCEDURE pro_innodb_lock_wait_check() BEGIN declare wait_rows int; set group_concat_max_len = 1024000; CREATE TABLE IF NOT EXISTS `innodb_lock_wait_log` ( `report_time` datetime DEFAULT NULL, `waiting_id` int(11) DEFAULT NULL, `blocking_id` int(11) DEFAULT NULL, `duration` varchar(50) DEFAULT NULL, `state` varchar(50) DEFAULT NULL, `waiting_query` longtext DEFAULT NULL, `blocking_current_query` longtext DEFAULT NULL, `blocking_thd_last_query` longtext, `thread_id` int(11) DEFAULT NULL ); select count(*) into wait_rows from information_schema.innodb_lock_waits ; if wait_rows > 0 THEN insert into `innodb_lock_wait_log` SELECT now(),r.trx_mysql_thread_id waiting_id,b.trx_mysql_thread_id blocking_id,concat(timestampdiff(SECOND,r.trx_wait_started,CURRENT_TIMESTAMP()),'s') AS duration, t.processlist_command state,r.trx_query waiting_query,b.trx_query blocking_current_query,group_concat(left(h.sql_text,10000) order by h.TIMER_START DESC SEPARATOR ';\n') As blocking_thd_query_history,thread_id FROM information_schema.innodb_lock_waits w JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id LEFT JOIN performance_schema.threads t on t.processlist_id = b.trx_mysql_thread_id LEFT JOIN performance_schema.events_statements_history h USING(thread_id) group by thread_id,r.trx_id order by r.trx_wait_started; end if; END ;;
2.3 創建事件
事件 每隔 5 秒 (通常等于 innodb_lock_wait_timeout 的值)執行一次,持續監控 7 天,結束后會自動刪除事件,也可以自定義保留時長。
use innodb_monitor; delimiter ;; CREATE EVENT `event_innodb_lock_wait_check` ON SCHEDULE EVERY 5 SECOND STARTS CURRENT_TIMESTAMP ENDS CURRENT_TIMESTAMP + INTERVAL 7 DAY ON COMPLETION NOT PRESERVE ENABLE DO call pro_innodb_lock_wait_check(); ;;
2.4 事件啟停
--1為全局開啟事件,0為全局關閉 mysql > SET GLOBAL event_scheduler = 1; --臨時關閉事件 mysql > ALTER EVENT event_innodb_lock_wait_check DISABLE; --關閉開啟事件 mysql > ALTER EVENT event_innodb_lock_wait_check ENABLE;
再根據應用日志報錯時間點及 SQL 分析 innodb_lock_wait_log 表。其中主要有 2 種場景:
鴻蒙官方戰略合作共建——HarmonyOS技術社區
blocking_current_query 不為空,說明阻塞事務處于運行狀態,這時候需要分析當前運行 SQL 是否存在性能問題。
blocking_current_query 為空,state 為 Sleep,此時阻塞事務處于掛起狀態,即不再運行 SQL,此時需要通過分析 blocking_thd_last_query 分析事務上下文,注意該列中的 SQL 為時間降序,即從下往上執行。
關于MySQL 行鎖超如何排查問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。