Closed 007gzs closed 6 years ago
首先这么设计当然是有原因的
tormysql是异步io的mysql driver,所以所有可能设计到io操作的函数都必须用coroutine包裹,并等待协程完成。
python2中with语法是无法使用coroutine并yield等待协程执行完成的,所以才在python2下是无法用with语法中自动rollback或commit的。
在python3下,有async with的支持,所以可用在with语法中自动rollback或commit,而这个确实也在啊async的with语法中实现了,只不过是用exec执行字符串的方式定义了这两个函数,之所以要这么做也是在python2下有async语法会直接语法错误无法使用,而用exec执行字符串定义行数本身也没有什么问题。
pymysql是同步io的库,两者不能同类比啊。 整个库已经在生产环境中高并发场景下证明在链接管理,事务提交上确实是没有问题的,稳定性和性能确实已经是所以异步io场景下最高的了。
目前我们在使用时候有个问题 tormysql 和 pymysql 默认autocommit都是False 在mysql 5.6及以上执行
sql = "select * from test limit 1"
with (yield self.pool.Connection()) as connection:
with connection.cursor() as cursor:
yield cursor.execute(sql)
datas = cursor.fetchall()
后 该事务未提交,状态仍为RUNNING状态,此时如果执行DDL命令的话就会 卡死,Waiting for table metadata lock,这样我们每次用with 链接数据库时都要增加try finally 来处理事务,失去了with的意义, 尤其是执行select的情况下,应用层做事务处理感觉很怪
python3可以用async with,python2没有其他办法了,只能应用层commit。
你的这个虽然能commit,但是with退出时并没有等待commit提的到数据库完成,但这时立刻又会把链接放入链接池,并发稍高就会立刻被另一个请求使用,mysql协议是不支持同时两个request的。
为了尽可能提高性能,链接池管理是栈式的,最后放入的将会最先选择被下一次使用。
我们也实际在生产环境使用,应用层commit确实麻烦,但想来想去python2确实没有其他方案了,所以最近开始升级python3。。
aexit里我看原来也没有事务逻辑
哦,忘了,是在helper里边提供了,简单操作的话可以直接使用helper的pool,直接在pool上提供execute操作,这也是PyMySQL/Tornado-MySQL的实现方式。
或许确实可以常规链接在async下也提供自动commit的操作,我想想。
https://github.com/snower/TorMySQL/pull/36/commits/53e3d1b1e7944a426ff6e1d5ca075643390b1530 这个原来怎么是先del 后判断,这不直接报错么。。
重新修改了
pymysql 中
执行后会自动处理事务
On successful exit, commit. On exception, rollback
但是tormysql中没有对事务做操作,作者是有什么其他考虑么@snowerhttps://github.com/PyMySQL/PyMySQL/blob/2fca94f24302591ba54e473d7a5cacba4111ae84/pymysql/connections.py#L500-L504