mysql 执行sql脚本_分享两个实用脚本--MySQL数据库一键定位阻塞事务源头SQL

概述

很多时候我们在MySQL数据库中会经常出现事务之间阻塞的问题,也就是阻塞lock,oracle的话实际上之前提供的脚本已经可以很直观看出阻塞的问题,那么对于mysql数据库我们应如何快速查找定位问题根源?

之前分享了innotop工具和show engine innodb status都不能很好的解决我们的需求,所以今天主要基于几张事务表来写sql看能不能定位到。


一、环境准备

数据库:mysql5.7.24 操作系统:centos7.3

1、数据准备

create database t DEFAULT CHARSET utf8 COLLATE utf8_general_ci;use t;create table test_blocking(id int primary key, name varchar(12));insert into test_blocking select 1, 'hwb' from dual;insert into test_blocking select 2, 'hwb2' from dual;insert into test_blocking select 3, 'hwb3' from dual;
34c0a02a3f0e7025b92e70b8e798267d.png

2、参数设置

为了实验效果,我们先将参数innodb_lock_wait_timeout设置为100,否则很快就会提示ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

show variables like 'innodb_lock_wait_timeout';set global innodb_lock_wait_timeout=100 ;
0af898b7e51293cd40c739a44d379102.png

二、被阻塞环境模拟及定位

1、第一个会话

select connection_id() from dual;set session autocommit=0;select * from test_blocking where id=1 for update;
1c7922654af1ae8a9c0458276c84ade4.png

2、第二个会话

在第二个连接会话中执行更新脚本

select connection_id() from dual;update test_blocking set name='kk' where id=1;
e4cdba89221f6a21812f1b0967b15a17.png

3、第三个会话--通过查询information_schema数据库下与事务相关的几个系统表

--查看哪个线程被哪个堵塞,waiting_thread_id代表等待线程,blocking_thread_id代表堵塞线程SELECTr.trx_id waiting_trx_id,r.trx_mysql_thread_id waiting_thread_id,r.trx_query waiting_query,b.trx_id blocking_trx_id,b.trx_mysql_thread_id blocking_thread_id,b.trx_query blocking_query,now( ) - r.TRX_STARTED blocking_time FROMinformation_schema.innodb_lock_waits wINNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_idINNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id; --查看源头sqlSELECTa.sql_text,c.id,d.trx_started,b.processlist_user,b.processlist_host FROMPERFORMANCE_SCHEMA.events_statements_current aJOIN PERFORMANCE_SCHEMA.threads b ON a.thread_id = b.thread_idJOIN information_schema.PROCESSLIST c ON b.processlist_id = c.idJOIN information_schema.innodb_trx d ON c.id = d.trx_mysql_thread_id WHEREc.id = 304192 ORDER BYd.trx_started;

如下截图所示,第一个SQL语句能够查到线程304193被线程304192阻塞了, 被阻塞的SQL语句为“update test_blocking set name='kk' where id=1;”, 能够查到被阻塞了多长时间,但是无法查到源头SQL语句。此时就需要第二个SQL语句登场,找到源头语句。

662595a2fe72a83dc8920caef3920042.png

ps:附一段查看阻塞线程更多信息的sql

SELECTp2.HOST Blockedhost,p2.USER BlockedUser,r.trx_id BlockedTrxId,r.trx_mysql_thread_id BlockedThreadId,TIMESTAMPDIFF( SECOND, r.trx_wait_started, CURRENT_TIMESTAMP ) WaitTime,r.trx_query BlockedQuery,l.lock_table BlockedTable,m.lock_mode BlockedLockMode,m.lock_type BlockedLockType,m.lock_index BlockedLockIndex,m.lock_space BlockedLockSpace,m.lock_page BlockedLockPage,m.lock_rec BlockedLockRec,m.lock_data BlockedLockData,p.HOST blocking_host,p.USER blocking_user,b.trx_id BlockingTrxid,b.trx_mysql_thread_id BlockingThreadId,b.trx_query BlockingQuery,l.lock_mode BlockingLockMode,l.lock_type BlockingLockType,l.lock_index BlockingLockIndex,l.lock_space BlockingLockSpace,l.lock_page BlockingLockPage,l.lock_rec BlockingLockRec,l.lock_data BlockingLockData,IF( p.COMMAND = 'Sleep', CONCAT( p.TIME, ' seconds' ), 0 ) idel_in_trx FROMinformation_schema.INNODB_LOCK_WAITS wINNER JOIN information_schema.INNODB_TRX b ON b.trx_id = w.blocking_trx_idINNER JOIN information_schema.INNODB_TRX r ON r.trx_id = w.requesting_trx_idINNER JOIN information_schema.INNODB_LOCKS l ON w.blocking_lock_id = l.lock_id AND l.lock_trx_id = b.trx_idINNER JOIN information_schema.INNODB_LOCKS m ON m.lock_id = w.requested_lock_id AND m.lock_trx_id = r.trx_idINNER JOIN information_schema.PROCESSLIST p ON p.ID = b.trx_mysql_thread_idINNER JOIN information_schema.PROCESSLIST p2 ON p2.ID = r.trx_mysql_thread_id ORDER BYWaitTime DESC G;
804b69e5e92101ab361ac643d884affe.png

这里不要太天真的认为第二个SQL语句能够获取所有场景下的阻塞源头SQL语句,实际业务场景,会话可能在执行一个存储过程或复杂的业务,有可能它执行完阻塞源头SQL后,继续在执行其它SQL语句,此时,你抓取的是这个连接会话最后执行的SQL语句。觉得有用的朋友多帮忙转发哦!后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注下~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值