【问题背景】
使用Python的MySQL库的MySQLdb.connect方法建立数据库连接之后,会自动发送set autocommit=0,开启一个事务,如果用户不主动提交,这个事务不会被提交。这往往不是使用者的本意。在这种情况下如果用户的更新请求会失效。
【问题剖析】
MySQLdb库的connections.py源码中,Connection类的__init__方法最后,有如下几行代码:

可以看出,当self.server_capabilities
& CLIENT.TRANSACTIONS 为真时,connectiont对象在初始化的最后会执行self.autocommit(False),即向server端发送一个set commit=0的SQL。
其中CLIENT.TRANSACTIONS在constants/CLIENT.py里被定义为8192,二进制是0010 0000 0000 0000;
server_capabilities①是mysql客户端认证协议包里的2个字节的一个标志包,当server端支持事务时,会置标志位CLIENT_TRANSACTIONS为0x00002000,二进制也是0010 0000
0000 0000。
综上,只要server端支持事务,客户端必然会发送一个set
autommit=0。
从230行那个注释来看,貌似是PEP-249②要求这样做,PEP-249是python对于数据库接口的规范。里面对commit做了如下要求:
.commit()
Commit any pending transaction to the
database.
Note
that if the database supports an auto-commit feature, this must be initially
off. An interface method may be provided to turn it back on.
Database modules that do not support
transactions should implement this method with void functionality.
加粗部分大意是,如果数据库支持自动提交,自动提交的特性需要在初始化时被关闭。
【问题解决】
一般情况下推荐方法1;3和4算是一种变通解决的方法。
【方法1:连接之后客户端后立即重新开启自动提交】
在建立数据库连接之后,调用autocommit(True)方法,或者执行set autocommit=1,重新开启事务自动提交:
conn1 = MySQLdb.connect(host=host, port=port, user=user,
passwd=passwd, db=db,charset="utf8");
conn1.autocommit(True);
#或者cursor1.execute("set
autocommit=1");
【方法2:在关闭连接前开启自动提交】
也就是说还是在事务中进行query,只是在关闭链接前提交:
【方法3:修改connections.py代码】
删除设置关闭自动提交的那几行代码。
【方法4:使用mysql官方的Connector/Python】
这个库④可以在connect的时候,指定是否开启autocommit,不过默认也是关闭。




