Flush tables 简介
官方手册中关于 Flush tables 的介绍, 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 tables 的一个效果就是会等待所有正在运行的 SQL 请求结束。
因为,SQL 语句在执行前,都会打开相应的表对象,如 select * from t1 语句,会找到 t1 表的 frm 文件,并打开表内存对象。为了控制表对象使用的内存空间和其他资源,MySQL 会隐式(后台表对象管理线程)或显式(flush tables 等)来关闭已打开但并没有使用的表对象。
然而,正在使用的表对象是不能关闭的(如 SQL 请求仍在运行),因此,Flush Tables 操作会被正在运行的 SQL 请求阻塞。
Flush tables 影响
1)flush tables 会等待正在运行的所有语句执行结束,即使运行的是查询请求;
2)如果 flush tables 等待 SQL 请求操作的表集合为{tables},这里的 tables 组合应该是当前正在有 sql 在运行的,已经打开的表,同一个库中,没有 sql 运行的表是不计算在内,因此若库 star 中有 3 张表,tx1 和 tx2 被打开了,,的若有新请求操作{tables}中的任意一表,这些请求都会阻塞(即使是普通查询),如会话 3;
3)如果其他会话新请求操作{tables}外的其他表,不会被阻塞,如会话 4。
从此可知,flush tables 操作可认为是{tables}所有表的表级排他锁,会阻塞其他会话关于{tables}表上的所有操作。假设一个大查询或长事务过程中(如会话 1)执行 flush tables 操作,那么 flush tables 会等待长事务的结束(如会话 1),同时阻塞关于{tables}的新请求。
Flush tables with read lock
Flush tables with read lock 是另一个常见的操作,与 Flush tables 的作用是一样的,同样会等待所有正在运行的 SQL 请求结束,只是增加了一个全局读锁,即阻塞所有库所有表的写操作,直到 unlock tables 操作完成。
1)与 flush tables 一样,flush tables with read lock 会等待正在运行的所有语句执行结束。
2)如果 flush tables with read lock 等待 SQL 请求操作的表集合为{tables},若有新请求操作{tables}中的任意一表,这些请求都会阻塞。
a) 如果是查询请求,在 flush tables with read lock 结束后就可执行。
b) 如果是插入、更新等写请求,必须等待 unlock tables 释放读锁。
3)如果其他会话新请求操作{tables}外的其他表,则
a) 如果是查询请求,不会被阻塞。
b) 如果是写请求,必须等待 unlock tables 释放读锁
因此,flush tables with read lock 操作是{tables}所有表的表级排他锁,同时是库级读锁,会阻塞库上所有写操作,直到执行 unlock tables。其影响面比 flush tables 更大。也就是比 flush tables 多一点影响,阻塞了{tables}之外的表的写操作,不影响其读操作,只有 unlock tables 之后,释放了这个对库的全局读锁之后,才可以写。