Django修改表结构导致MySQL表锁死waiting for meta lock的问题

最近我们在使用south对django做schemaigration的过程,经常遇到mysql锁死“waiting for meta lock”的现象。

这种应该是mysql内里有长时间未提交的事务,然后去做alter table的时候会等待事务提交,这样一来就锁死了,连访问表都不行。

通过 select * from information_schema.innodb_trx\G; 查看未提交的事务,发现程序一启动就有几个长期在那里,状态一直是RUNING。

监控mysql的sql log发现启动程序后会执行这么几个命令:

263 Query	SET NAMES utf8
263 Query	set autocommit=0
263 Query	SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;SET NAMES utf8mb4
263 Query	SET SQL_AUTO_IS_NULL = 0

关键在那个 set autocommit=0

后面那个是我们在Django的settings DATABASES default 节点里面加的:

'OPTIONS': { "init_command": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED", "charset":"utf8mb4"},

最后找到是 MySQL-python 库的问题,1.2.4 版本中强制设置了 autocommit=False,新版本中加入了参数,可以设置了。具体可以看 connections.py 中 reconnection 方法的代码。

所以升级到1.2.5后,再在django的 DATABASES default 加个OPTIONS就好了:

'OPTIONS': { "init_command": "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED", "charset":"utf8mb4", 'autocommit': True },