最近我们在使用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 },