MySQL 显示使用lock table

MySQL 显示使用lock table,第1张

lock table与事务之间相互影响。因此建议除了在事务中禁用了AUTOCOMMIT, 可以使用lock table之外。其他任何时候都不要显示执行lock table,不管是使用任何存储引擎。

注:之处的locke table *** 作是由服务层自身实现的表级锁,并非是存储引擎的锁类

在项目的一次需求中,需要对一个表增加字段,然而在执行增加字段的sql语句时,卡住了很久都没提交到Mysql完成,而此时对外接口服务请求也卡住了,这时中断卡住的alter table 语句,服务慢慢恢复正常,如果不搞清楚这个问题的根源,不敢增加字段,因为会直接影响到服务

通过show processlist 查看到在alter table语句执行卡住过程中,累计了大量状态为 Waiting for table metadata lock 的记录

然后查看当前的事务状态 执行 select * from information_schema.innodb_trx\G

发现了其中一条已经运行了很久的事务,我怀疑跟这个运行很久的而且没有提交的事务有关。

在本地mysql开多个终端测试

session 1: 开启事务,执行select 语句,但不提交事务

session 2:执行增加字段sql

执行被阻塞了

可以看到alter table语句的状态为Waiting for table metadata lock

session 3 : 再次查询t1表

也被阻塞了

select * from t1 再次查询t1表也是 Waiting for table metadata lock状态,说明由于 metadata lock的存在,会导致后面正常的查询都会因为等待锁而阻塞

再查看当前事务运行状态:

可以看到,session1的事务由于还没提交,所以这里能看到它的状态还是running

这时我们commit session1的事务,看看效果

session 1:

session 2:

session 3:

可以看到session1的事务提交后,session2 和session3 都正常执行了, 他们完成的时间分别是30秒和7秒

通过上面的还原测试,可以知道是由于事务没有提交而给表加了锁,导致后面alter语句因为等待锁而阻塞,从而影响后面的正常请求。

那说明我们的项目是默认开启了事务吗?

继续排查,项目是使用flask-sqlchemy的插件来管理mysql接入,然后查了下文档

在实例化sqlchemy的时候,会创建一个用于跟Mysql交互的session对象,看看源码

从 SignallingSession类的定义看来,autocommit=False,说明默认都给所有的sql执行开启事务,也就是说,哪怕是纯select语句,不需要加锁的select,我们的项目默认也需要开启事务,这对于Mysql MVCC的版本控制来说,是没必要的。

解决办法:就是在实例化SQLAlchemy的时候,给一个参数,修改的session的autocommit=True:

来自官网的介绍:

意思就是为了保证事务的串行执行,而启用的一个锁,这个锁只会在事务结束的时候释放,因此在事务提交或回滚钱,任何对这个表做的DDL *** 作,都是会阻塞的

这个 Metadata lock 是MySQL在5.5.3版本后引入了,为的是防止5.5.3以前的一个bug的出现:

当一个会话在主库执行DML *** 作还没提交时,另一个会话对同一个对象执行了DDL *** 作如drop table,而由于MySQL的binlog是基于事务提交的先后顺序进行记录的,因此在从库上应用时,就出现Q了先drop table,然后再向table中insert的情况,导致从库应用出错。

怎么解决mysql数据库只读,table sp

SELECT

CONCAT( 'UPDATE ', table_name, ' SET flag = 0'AS `准备要执行的sql`

FROM

information_schema.tables

WHERE

table_schema = 'database 的名字'

查询完毕以后,复制出查询结果, 粘贴一下, 执行。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/8325288.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-15
下一篇 2023-04-15

发表评论

登录后才能评论

评论列表(0条)

保存