mysql left join超时_关于锁:技术分享-MySQL-行锁超时排查方法优化

作者:xuty

本文起源:原创投稿

* 爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。

一、纲要

#### 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 未测试。

2.1 创立库

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 种场景:

blocking_current_query 不为空,阐明阻塞事务处于运行状态,这时候须要剖析以后运行 SQL 是否存在性能问题。

blocking_current_query 为空,state 为 Sleep,此时阻塞事务处于挂起状态,即不再运行 SQL,此时须要通过剖析 blocking_thd_last_query 剖析事务上下文,留神该列中的 SQL 为工夫降序,即从下往上执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值