暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

小白鼠之python的MySQLdb库autocommit研究

原创 小龙人7599 2022-07-01
2193

【问题背景】

使用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,只是在关闭链接前提交:cursor1.execute("set autocommit=1");

【方法3:修改connections.py代码】

        删除设置关闭自动提交的那几行代码。

【方法4:使用mysql官方的Connector/Python】

         这个库可以在connect的时候,指定是否开启autocommit,不过默认也是关闭。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论