MySQL 5.6中如何定位DDL被阻塞的问题
在上一篇文章《MySQL 5.7中如何定位DDL被阻塞的问题》中,对于DDL被阻塞问题的定位,我们主要是基于MySQL 5.7新引入的performance_schema.metadata_locks表。提出的定位方法,颇有种"锦上添花"的意味,而且,也只适用于MySQL 5.7开始的版本。
但在实际生产中,MySQL 5.6还是占绝不多数。虽然MySQL 8.0都已经GA了,但鉴于数据库的特殊性,在对待升级的这个事情上,相当一部分人还是秉持着一种“不主动”的态度。
既然MySQL 5.6用者众多,有没有一种方法,来解决MySQL 5.6的这个痛点呢?
还是之前的测试Demo
会话1开启了事务并执行了三个操作,但未提交,此时,会话2执行了alter table操作,被阻塞。
session1> begin;
Query OK, 0 rows affected (0.00 sec) session1> delete from slowtech.t1 where id=2;
Query OK, 1 row affected (0.00 sec) session1> select * from slowtech.t1;
+------+------+
| id | name |
+------+------+
| 1 | a |
+------+------+
row in set (0.00 sec) session1> update slowtech.t1 set name='c' where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0 session2> alter table slowtech.t1 add c1 int; ##被阻塞 session3> show processlist;
+----+------+-----------+------+---------+------+---------------------------------+------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------+------+---------+------+---------------------------------+------------------------------------+
| 2 | root | localhost | NULL | Sleep | 51 | | NULL |
| 3 | root | localhost | NULL | Query | 0 | starting | show processlist |
| 4 | root | localhost | NULL | Query | 9 | Waiting for table metadata lock | alter table slowtech.t1 add c1 int |
+----+------+-----------+------+---------+------+---------------------------------+------------------------------------+
rows in set (0.00 sec)
其实,导致DDL阻塞的操作,无非两类:
1. 慢查询
2. 表上有事务未提交
其中,第一类比较好定位,通过show processlist即能发现。而第二类基本没法定位,因为未提交事务的连接在show processlist中的输出同空闲连接一样。
如下面Id为2的连接,虽然Command显示为“Sleep”,其实是事务未提交。
mysql> show processlist;
+----+------+-----------+------+---------+------+---------------------------------+------------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------+------+---------+------+---------------------------------+------------------------------------+
| 2 | root | localhost | NULL | Sleep | 77 | | NULL |
| 3 | root | localhost | NULL | Query | 0 | starting | show processlist |
| 4 | root | localhost | NULL | Query | 44 | Waiting for table metadata lock | alter table slowtech.t1 add c1 int |
+----+------+-----------+------+---------+------+---------------------------------+------------------------------------+
3 rows in set (0.00 sec)
所以,网上有kill空闲(Command为Sleep)连接的说法,其实也不无道理,但这样做就太简单粗暴了,难免会误杀。
其实,既然是事务,在information_schema. innodb_trx中肯定会有记录,如会话1中的事务,在表中的记录如下,
mysql> select * from information_schema.innodb_trx\G
*************************** 1. row ***************************
trx_id: 1050390
trx_state: RUNNING
trx_started: 2018-07-17 08:55:32
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 4
trx_mysql_thread_id: 2
trx_query: NULL
trx_operation_state: NULL
trx_tables_in_use: 0
trx_tables_locked: 1
trx_lock_structs: 2
trx_lock_memory_bytes: 1136
trx_rows_locked: 3
trx_rows_modified: 2
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
1 row in set (0.00 sec)
其中trx_mysql_thread_id是线程id,结合performance_schema.threads,可以知道当前哪些连接上存在着活跃事务,这样就进一步缩小了可被kill的线程范围。
但从影响程度上,和kill所有Command为Sleep的连接没太大区别,毕竟,kill真正的空闲连接对业务的影响不大。
此时,依然可以借助performance_schema. events_statements_history表。
在上篇MySQL 5.7的分析中,我们是首先知道引发阻塞的线程ID,然后利用events_statements_history表,查看该线程的相关SQL。
而在MySQL 5.6中,我们并不知道引发阻塞的线程ID,但是,我们可以反其道而行之,利用穷举法,首先统计出所有线程在当前事务执行过的所有SQL,然后再判断这些SQL中是否包含目标表。
具体SQL如下,
SELECT
processlist_id,
sql_text
FROM
(
SELECT
c.processlist_id,
substring_index( sql_text, "transaction_begin;",-1 ) sql_text
FROM
information_schema.innodb_trx a,
(
SELECT
thread_id,
group_concat( CASE WHEN EVENT_NAME = 'statement/sql/begin' THEN "transaction_begin" ELSE sql_text END ORDER BY event_id SEPARATOR ";" ) AS sql_text
FROM
performance_schema.events_statements_history
GROUP BY
thread_id
) b,
performance_schema.threads c
WHERE
a.trx_mysql_thread_id = c.processlist_id
AND b.thread_id = c.thread_id
) t
WHERE
sql_text LIKE '%t1%'; +----------------+---------------------------------------------------------------------------------------------------------+
| processlist_id | sql_text |
+----------------+---------------------------------------------------------------------------------------------------------+
| 2 | delete from slowtech.t1 where id=2;select * from slowtech.t1;update slowtech.t1 set name='c' where id=1 |
+----------------+---------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)
从输出来看,确实也达到了预期效果。
需要注意的是,在MySQL5.6中,events_statements_history默认是没有开启的。
mysql> SELECT * FROM performance_schema.setup_consumers WHERE NAME LIKE '%statements%';
+--------------------------------+---------+
| NAME | ENABLED |
+--------------------------------+---------+
| events_statements_current | YES |
| events_statements_history | NO |
| events_statements_history_long | NO |
| statements_digest | YES |
+--------------------------------+---------+
4 rows in set (0.00 sec)
MySQL 5.6中如何定位DDL被阻塞的问题的更多相关文章
- MySQL 5.7中如何定位DDL被阻塞的问题
在上篇文章<MySQL表结构变更,不可不知的Metadata Lock>中,我们介绍了MDL引入的背景,及基本概念,从“道”的层面知道了什么是MDL.下面就从“术”的层面看看如何定位MDL ...
- MySQL 中如何定位 DDL 被阻塞的问题
经常碰到开发.测试童鞋会问,线下开发.测试环境,执行了一个DDL,发现很久都没有执行完,是不是被阻塞了?要怎么解决? 包括在群里,也经常会碰到类似问题:DDL 被阻塞了,如何找到阻塞它的 SQL ? ...
- 【mysql】数据库中的DML DDL DCL TCL 及 Online DDL
DDL(data definition language) : 数据库定义语言 用来定义创建操作表的时候用到的一些sql命令,比如CREATE.ALTER.DROP等等. DML(data manip ...
- 物联网应用中实时定位与轨迹回放的解决方案 – Redis的典型运用(转载)
物联网应用中实时定位与轨迹回放的解决方案 – Redis的典型运用(转载) 2015年11月14日| by: nbboy| Category: 系统设计, 缓存设计, 高性能系统 摘要 ...
- mysql init-file参数中语句限制
mysql 启动选项中的init-file文件的内容目测只能是dml语句,不能包含ddl,否则执行就会报错,但不影响启动本身..太扯了..
- MySQL InnoDB 修改表列Online DDL
概述 一般来说数据库结构一经设计,不能轻易更改,因为更改DDL(Data Definition Language)操作代价很高,所以在进行数据库结构设计时需要谨慎. 但是业务发展是未知的,特别是那些变 ...
- MySQL 并行复制演进及 MySQL 8.0 中基于 WriteSet 的优化
MySQL 8.0 可以说是MySQL发展历史上里程碑式的一个版本,包括了多个重大更新,目前 Generally Available 版本已经已经发布,正式版本即将发布,在此将介绍8.0版本中引入的一 ...
- mysql删除表中的记录
大家都知道,在MySQL中删除一个表中的记录有两种方法,一种是DELETE FROM TABLENAME WHERE... , 还有一种是TRUNCATE TABLE TABLENAME. DELET ...
- MySQL 5.6 中一个重要的优化——Index Condition Pushdown,究竟push down了什么
1 问题描述 一条SQL,在数据库中是如何执行的呢?相信很多人都会对这个问题比较感兴趣.当然,要完整描述一条SQL在数据库中的生命周期,这是一个非常巨大的问题,涵盖了SQL的词法解析.语 ...
随机推荐
- Web前端:博客美化:二、鼠标特效
1.获取JS权限 因为是js代码所以需要放在 侧边栏公告 里 没开通之前,有一个申请的链接,点击即可,我是第二天才看到过审的 ^-^ 2.Ctrl+C.Ctrl+V 数组里的文字随自己心情啦 另:30 ...
- Java 一些知识点总结
本篇文章会对面试中常遇到的Java技术点进行全面深入的总结,帮助我们在面试中更加得心应手,不参加面试的同学也能够借此机会梳理一下自己的知识体系,进行查漏补缺(阅读本文需要有一定的Java基础).本文的 ...
- Oracle数据库忘记用户名密码的解决方案
1.windows+r输入sqlplus 2.依次输入: sys/manager as sysdba #创建新用户 SQL> create user c##username(自己的用户名) id ...
- Greenplum源码安装(CentOS 7)
最近在看GP,在安装集群的时候遇到了很多问题,在此记录下来. 目录 1 安装环境及软件版本 2 安装准备工作 2.1 修改hosts(所有机器) 2.2 修改系统内核配置(所有机器) 2.3 关闭 ...
- Django之--模板加载图片
在使用Django加载图片时遇到了一些问题,在模板html文件中无论使用绝对路径还是当前相对路径都无法找到图片,一直报403和404的错误,后来结合官网和网上的其他资料总算是成功了,这里记下来. 参考 ...
- Linux:固定 ip
默认情况下,安装完操作系统时,ip是采用dhcp来动态分配的.通常我们需要将其固定下来. 不然 每次系统重启后,ip都会变动,这样会给日常工作带来不必要的麻烦的. 下面就是在rhel .centos ...
- 强大的Notepad++,竟然还是自由使用的
这么好用的工具,竟然还是可以自由使用的的,当然就不用去找某些软件的破解版了. 除了本身很好用,还有插件功能,插件许多也是自由使用的,利用插件就可以实现程序员需要的一个手工编辑器了.
- orcFile split和读数据原理总结(hive0.13)
http://blog.csdn.net/zhaorongsheng/article/details/72903431 官网关于orcfile的介绍 背景 Hive的rcfile格式已经使用多年,但是 ...
- 官网下载Git方法
最近去官网下载Git,奇慢,下到一半直接挂掉,挂VPN也是一样 https://git-scm.com/ 今天学到一个方法,下载速度可以达到2m/s,那就是复制下载地址,用迅雷下载,可能是迅雷有P2 ...
- 用js检测文本框中输入的是否符合条件并有错误和正确提醒
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...