MySQL Flush导致的等待问题
--MySQL Flush导致的等待问题
-------------------------------2014/07/13
前言
在实际生产环境中有时会发现大量的sql语句处于waiting for table.. 状态中,有时候看起来会让人觉得困惑,本文将讲解此状态产生的原因及解决办法。
正文
本文中用到了lock table来模拟实际情况, 首先介绍一个lock tables需要注意的事项,如果在一个session中使用了lock tables,那么在此session中将只能访问获取到lock的表。官方解释:
If the LOCK TABLES statement must wait due to locks held by other sessions on any of the tables, it blocks until all locks can be acquired.
A session that requires locks must acquire all the locks that it needs in a single LOCK TABLES statement. While the locks thus obtained are held, the session can access only the locked tables. For example, in the following sequence of statements, an error occurs for the attempt to access t2 because it was not locked in the LOCK TABLES statement:
mysql> LOCK TABLES t1 READ;
mysql> SELECT COUNT(*) FROM t1;
+----------+
| COUNT(*) |
+----------+
| 3 |
+----------+
mysql> SELECT COUNT(*) FROM t2;
ERROR 1100 (HY000): Table 't2' was not locked with LOCK TABLES
Tables in the INFORMATION_SCHEMA database are an exception. They can be accessed without being locked explicitly even while a session holds table locks obtained with LOCK TABLES.
基于这样的原因,往往在备份时选择flush table with read lock;是个不错的选择,如果成功,它会锁住所有表。
回顾一下官方文档关于flush table的解释
Closes all open tables, forces all tables in use to be closed, and flushes the query cache. FLUSH TABLES also removes all query results from the query cache, like the RESET QUERY CACHE statement.
模拟Flush操作导致的waiting tables等待问题。
a) 在终端1中执行lock table锁住jackjhu库中的一张表
mysql> lock table t1 read;
Query OK, 0 rows affected (0.00 sec)
b) 在终端2中执行flush tables
mysql> flush tables;
--无返回,被阻塞..
c) 此时终端3欲连接到jackjhu库,如果mysql连接时没有使用-A,将出现阻塞。
mysql> use jackjhu
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
--无返回,被阻塞,后面会解释原因…
重新使用-A选项连接终端3执行select jackjhu库中表t1,阻塞。
mysql> select * from t1;
--无返回,被阻塞..
d) 新建终端4,使用-A选项连接mysql,到jackjhu库中查询其他表,正常。
mysql> select * from t2;
+----+---------+
| id | name |
+----+---------+
| 5 | mysql |
| 6 | test |
+----+---------+
2 rows in set (0.01 sec)
退出终端,重新使用不带-A选项连接mysql,选中jackjhu。
mysql> use jackjhu
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
--无返回,被阻塞..
查看现在的线程情况,并分析阻塞的原因。
mysql> show full processlist;
+----+------+-----------+---------+------------+------+-------------------------+-----------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------+---------+------------+------+-------------------------+-----------------------+
| 2 | root | localhost | jackjhu | Query | 0 | init | show full processlist |
| 3 | root | localhost | jackjhu | Query | 33 | Waiting for table flush | flush tables |
| 7 | root | localhost | jackjhu | Query | 20 | Waiting for table flush | select * from t1 |
| 12 | root | localhost | jackjhu | Field List | 10 | Waiting for table flush | |
+----+------+-----------+---------+------------+------+-------------------------+-----------------------+
4 rows in set (0.00 sec)
首先查看waiting for table ..的官方解释:
The thread got a notification that the underlying structure for a table has changed and it needs to reopen the table to get the new structure. However, to reopen the table, it must wait until all other threads have closed the table in question.
This notification takes place if another thread has used FLUSH TABLES or one of the following statements on the table in question: FLUSH TABLES tbl_name, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE, orOPTIMIZE TABLE.
分析
ID 3:终端2,由于t1被终端1锁住(lock table t1 read),flush操作中需要刷新表t1缓冲并关闭表,被阻塞,表被锁无法关闭。
ID 7:终端3,查询t1表的内容,由于查询前有flush操作,flush操作会发出表需要被重新打开的信号。终端3的查询需要重新打开t1表,显然也被阻塞,由我们上面的实验知道,打开其他没有被锁定的表是可以的,他们已经完成flush并可以被打开。
ID 12:不使用-A连接mysql,被阻塞。线程状态:Field List。解释:
The thread is retrieving information for table columns.
由于表t1需要被reopen阻塞,所以这里也被阻塞。
从show full processlist这个表象上看,好像是flush tables引起的问题,其实问题的根源在于这个操作被阻塞,也就是表t1被锁住,或无法释放被关闭。
同样ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE, OPTIMIZE TABLE等操作也会出现这样的问题,这面是实验结果。
条件1:lock table t1 read
repair table, alter table(create index…),rename table,optimize table
以上操作和之后的select出现 Waiting for table metadata lock
analyze table t1操作正常,但是后面的select出现 Waiting for table metadata lock
--无field List锁
条件2:lock table t1 write
仅仅说一下和条件1中情况不同的,其他一样。
analyze table
以上操作和之后的select出现 Waiting for table metadata lock
--无field List锁
注意这里使用了lock table .. read简单的进行了模拟,实际上生产环境中大多数是由于长查询,导致flush table一直等待无法关闭该表导致。
MySQL Flush操作的bug
现象:如上文模拟的情况,如果在生产环境中发现waiting for table flush,阻塞了大量的sql。这时候为了解决问题,kill掉flush tables这个操作,这并不能解决问题, 需要reopen的标记依然会存在而没有被清除,后面的select依然没能被继续。
MySQL Bug: http://bugs.mysql.com/bug.php?id=44884
出现waiting for table.. 的解决办法
找到阻塞FLUSH TABLES, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE, OPTIMIZE TABLE等操作的源头,或许是lock table操作和有表锁,或许是一个长长的查询(可以从proceelist的time列找到),总之,我们可以很容易定位到哪张表引起的问题,再去定位sql语句,从这个方向去思考,可以比较容易的解决这样的问题。
最后看看flush tables with read lock的行为,先看看官方解释:
Closes all open tables and locks all tables for all databases with a global read lock.
关闭打开的表。
mysql> flush table with read lock;
Query OK, 0 rows affected (0.00 sec)
mysql> show global status like '%open%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| Com_ha_open | 0 |
| Com_show_open_tables | 0 |
| Open_files | 7 |
| Open_streams | 0 |
| Open_table_definitions | 0 | --表结构文件被关闭
| Open_tables | 0 | --表被关闭
| Opened_files | 561 |
| Opened_table_definitions | 101 |
| Opened_tables | 101 |
| Slave_open_temp_tables | 0 |
+--------------------------+-------+
10 rows in set (0.00 sec)
给mysql全局的读锁。
mysql> flush table with read lock;
Query OK, 0 rows affected (0.00 sec)
mysql> show global status like '%open%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| Com_ha_open | 0 |
| Com_show_open_tables | 0 |
| Open_files | 7 |
| Open_streams | 0 |
| Open_table_definitions | 0 |
| Open_tables | 0 |
| Opened_files | 561 |
| Opened_table_definitions | 101 |
| Opened_tables | 101 |
| Slave_open_temp_tables | 0 |
+--------------------------+-------+
10 rows in set (0.00 sec)
对于写入操作近些阻塞,写入操作被锁等待
mysql> insert into t3 values(3,'uncommit');
--无返回,等待,processlist中状态如下:
|Query | 37 | Waiting for global read lock | insert into t3 values(3,'uncommit') |
如果事务在flush with read lock前已经有数据写入,但是还没有提交,此时提交的话也会被阻塞。
Query | 3 | Waiting for commit lock | commit
MySQL Flush导致的等待问题的更多相关文章
- 转 mysql 备份导致 waiting for global read lock
######转 https://blog.csdn.net/weixin_34038652/article/details/92129498 近业务高峰期间经常会有开发跳起来说应用连接数据库超时了! ...
- MySQL flush privileges 명령어
INSERT나 UPDATE, DELETE문을 이용해서 MySQL의 사용자를 추가,삭제하거나, 사용자 권한 등을 변경하였을 때, MySQL에 변경사항을 적용하기 위해서 사용하는 명령 ...
- MySQL flush tables with read lock
mysql> flush tables with read lock; flush tables with read lock 会去关闭已经打开的所有文件,它要做这个操作就先要拿到锁:当发起这个 ...
- MySQL skip-character-set-client-handshake导致的一个字符集问题
http://www.quweiji.com/mysql-skip-character-set-client-handshake%E5%AF%BC%E8%87%B4%E7%9A%84%E4%B8%80 ...
- 8.0 以上版本 mySQL数据库导致的命令行可连接,NaviCat不可连接的问题
错误代码: client does not support authentication 原因: 没有开启Mysql的远程连接配置 解决办法: 1 使用命令行进入数据库 C:\Users\wushao ...
- MySQL 事务没有提交导致 锁等待 Lock wait timeout exceeded
java.lang.Exception: ### Error updating database. Cause: java.sql.SQLException: Lock wait timeout e ...
- 排查MySQL事务没有提交导致 锁等待 Lock wait timeout exceeded
解决思路: select * from information_schema.innodb_trx 之后找到了一个一直没有提交的只读事务, kill 到了对应的线程后ok 了. 转载自:http:// ...
- 【MySQL】事务没有提交导致 锁等待Lock wait timeout exceeded异常
异常:Lock wait timeout exceeded; try restarting transaction 解决办法:(需要数据库最高权限) 执行select * from informati ...
- mysql flush操作
FLUSH语法 FLUSH [LOCAL | NO_WRITE_TO_BINLOG] flush_option [, flush_option] ... 如果您想要清除MySQL使用的部分内部缓存,您 ...
随机推荐
- sql将一列数据拼成一个字符串的方法
SELECT STUFF(CONVERT(VARCHAR(500), ( SELECT TOP 10 ',' + BG_Country FROM dbo.BS_Budget FOR XML PATH( ...
- Vijos 1033 整数分解(版本2)
描述 整数分解(版本2) 一个正整数可以分解成若干个自然数之和.请你编一个程序,对于给出的一个正整数n(1<=n<=1500),求出满足要求的分解方案,并使这些自然数的乘积m达到最大. 例 ...
- 使用matplotlib快速绘图
matplotlib的pyplot子库提供了和matlab类似的绘图API,方便用户快速绘制2D图表.让我们先来看一个简单的例子: # -*- coding: utf-8 -*- import num ...
- 【原】无脑操作:Windows 10 + MySQL 5.5 安装使用及免安装使用
本文介绍Windows 10环境下, MySQL 5.5的安装使用及免安装使用 资源下载: MySQL安装文件:http://download.csdn.net/detail/lf19820717/9 ...
- 小解系列-解决WebUploader在谷歌浏览器下弹出框打开慢,在Bootstrap模态框内部多次点击才能触发的问题
WebUploader百度前端团队开源的上传组件,用起来感觉真心不错的,标题的两个问题是我实际使用过程中遇到的问题,经过百度和谷歌查到解决方案, 特分享一下,以供遇到此问题的童靴. 谷歌浏览器弹出框打 ...
- webgl自学笔记——几何图形
3D应用的基础元素: 1.canvas,它是渲染场景的占位符.标准html的canvas元素 2.Objects,这里指的是组成一个场景的所有3d实体.这些实体都由三角形组成.webgl中使用Buff ...
- Java开发环境的搭建及配置
1.首先下载并安装jdk,jdk和jre最好安装在同一文件夹的不同目录文件中,jdk安装完后就是进行环境变量的配置. JDK的环境变量配置: (1)新建变量JAVA_HOME , 值为 jdk安 ...
- 虚拟机Linux系统下配置网络
虚拟机上安装Redhat9.0后是没有网络的,而本来的Windows系统是可以上网的,此时想在Redhat上网就需要在Linux系统上配置网络,以下是笔者自己配置的一点心得. 1.电脑本机系统打开网络 ...
- Ansible 运维自动化 ( 配置管理工具 )
背景 出差背景,要搞项目的自动化部署.因为只直接对接生产分发,机器又非常多,这样以往使用的bat只能作为应急方案了,还是得考虑使用专业化的工具来做这个事情! 当下有许多的运维自动化工具( 配置管理 ) ...
- vue2中component父子组件传递数据props的使用
子组件使用父亲传过来的数据,我们需要通过子组件的 props 选项. 组件实例的作用域是孤立的,不能在子组件的模板内直接引用父组件的数据.修改父亲传过来的props数据的时候 父亲必须传递对象,否则不 ...