Mysql 死锁过程及案例详解之清空缓存锁Flush Locks

Posted ShenLiang2025

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql 死锁过程及案例详解之清空缓存锁Flush Locks相关的知识,希望对你有一定的参考价值。

mysql 清空缓存锁Flush Locks 

清空缓存锁Flush Locks

flush table的功能是关闭所有打开的表,强制关闭所有正在使用的表,并刷新准备好的语句缓存。

这种操作需要用户拥有 FLUSH_TABLESRELOAD权限。

flush tables在已经锁定表(对应LOCK TABLES ... READ语句)的情况下不能使用,刷新和锁定表一般用FLUSH TABLES tbl_name ... WITH READ LOCK语句。

在我们需要做备份时为了同时防止有新数据写入,那么备份时我们一般通过如下命令刷新并锁定表:FLUSH TABLES WITH READ LOCK;

该操作实现的功能即是关闭所有的表并通过全局读锁锁定所有数据库里的所有表。

而这里的flush lock即是在使用FLUSH TABLES语句时被获取的,它在语句执行期间会一直持续,除非是FLUSH TABLES添加WITH READ LOCK选项,因为在这种情况下共享(读)锁将被持有,直到锁显式释放。

执行ANALYZE table语句后会触发一个隐式的表刷新。

flush lock可通过参数锁等待超时时间(lock_wait_timeout)来设置,如果等待时间超过该参数还未获取锁则会放弃。如果通过kill杀死FLUSH TABLES语句也让锁自动放弃。然而由于mysql内部有个更低级的锁叫做表定义缓存(table definition cache)版本锁不会立即释放直至长时间运行的语句结束。这时解决锁问题的唯一办法就是杀掉长时间运行的语句对应的进程。

示意案例

-- Step1 连接1上执行按照id查询city的语句,这里sleep(180)秒只是为了让执行时间拉长。 
SELECT *, SLEEP(180) FROM city WHERE ID = 1056
 
-- Step2 连接2上执行按照id查询city的语句 
FLUSH TABLES world.city

-- Step3 连接3上执行按照id查询city的语句 
SELECT * FROM world.city WHERE ID = 1055

-- Step4 连接4上执行查看以上三个连接的会话信息。
SELECT thd_id, conn_id, state,
current_statement
FROM sys.session
WHERE current_statement IS NOT NULL
AND thd_id <> PS_CURRENT_THREAD_ID()

/*
执行结果
thd_id	conn_id	state	current_statement
48	9	User sleep	SELECT *, SLEEP(180) FROM city WHERE ID = 1056
50	11	Waiting for table flush	FLUSH TABLES world.city
49	10	Waiting for table flush	SELECT * FROM world.city WHERE ID = 1055
*/

这里我们通过sys.session来查看的结果,类似的也可以通过performance_shchema.threads或者命令show processlist查看。会话1里查看city表里id为1056的信息,会话2执行了刷新表操作,会话3执行查看city表里id为1055的信息,这是我们可以通过会话4里的系统表查看以上三个会话里的状态,可见会话2、3都是在“Waiting for table flush”即等待表刷新。

以上是关于Mysql 死锁过程及案例详解之清空缓存锁Flush Locks的主要内容,如果未能解决你的问题,请参考以下文章

Mysql 死锁过程及案例详解之用户自定义锁

Mysql 死锁过程及案例详解之用户自定义锁

Mysql 死锁过程及案例详解之元数据锁MetaData Lock

Mysql 死锁过程及案例详解之元数据锁MetaData Lock

Mysql 死锁过程及案例详解之记录锁与间隔锁Record Lock Gap Lock

Mysql 死锁过程及案例详解之插入意向锁与自增锁备份锁日志锁Insert Intention Lock Auto-increment Lock Backup Lock Log Lock