snower / TorMySQL

The highest performance asynchronous MySQL driver by PyMySQL
MIT License
308 stars 63 forks source link

with conn 退出时处理事务 #36

Closed 007gzs closed 6 years ago

007gzs commented 6 years ago

pymysql 中

with pymysql.connect(xxx) as conn:
    xxxx

执行后会自动处理事务 On successful exit, commit. On exception, rollback 但是tormysql中没有对事务做操作,作者是有什么其他考虑么@snower

https://github.com/PyMySQL/PyMySQL/blob/2fca94f24302591ba54e473d7a5cacba4111ae84/pymysql/connections.py#L500-L504

snower commented 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场景下最高的了。

007gzs commented 6 years ago

目前我们在使用时候有个问题 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的情况下,应用层做事务处理感觉很怪

snower commented 6 years ago

python3可以用async with,python2没有其他办法了,只能应用层commit。

你的这个虽然能commit,但是with退出时并没有等待commit提的到数据库完成,但这时立刻又会把链接放入链接池,并发稍高就会立刻被另一个请求使用,mysql协议是不支持同时两个request的。

为了尽可能提高性能,链接池管理是栈式的,最后放入的将会最先选择被下一次使用。

snower commented 6 years ago

我们也实际在生产环境使用,应用层commit确实麻烦,但想来想去python2确实没有其他方案了,所以最近开始升级python3。。

007gzs commented 6 years ago

aexit里我看原来也没有事务逻辑

snower commented 6 years ago

哦,忘了,是在helper里边提供了,简单操作的话可以直接使用helper的pool,直接在pool上提供execute操作,这也是PyMySQL/Tornado-MySQL的实现方式。

或许确实可以常规链接在async下也提供自动commit的操作,我想想。

007gzs commented 6 years ago

https://github.com/snower/TorMySQL/pull/36/commits/53e3d1b1e7944a426ff6e1d5ca075643390b1530 这个原来怎么是先del 后判断,这不直接报错么。。

snower commented 6 years ago

重新修改了