Python aiomysql 我遇到的异常情况

2019-03-20 23:18:09 +08:00
 nightstart

问题描述 用我自己封装的这个模块 会出现好几个问题

  1. insert 进去之后 select 然后会获取不到结果
  2. 我在命令行操作 mysql delete 一些数据 select 不会立马反应过来

两者都在我重启项目之后正常了 我感觉是缓存的问题

  1. 解决方案是在 insert 函数里面 尾部加入 cls.pool = None 相当于让这个 pool 失效了 下次重新建立 pool 读的是最新的数据。 但是这个解决方案对 2 没用 await cur.execute("commit;") await conn.commit() 这两者我都加了 但是感觉还是没起作用

那个 select 有缓存真的是醉了 读不到最新的数据 而且 cls.pool = None 就完全发挥不了连接池的作用了 求帮忙

class AioMysqlHelper:

    pool = None

    @classmethod
    async def get_pool(cls):

        if not cls.pool:
            cls.pool = await aiomysql.create_pool(**Config.mysql)

        return cls.pool

    @classmethod
    async def insert(cls, sql, params=None):
        params = params or []
        await cls.get_pool()
        async with cls.pool.acquire() as conn:
            async with conn.cursor() as cur:
                try:
                    await cur.execute(sql, params)
                    await cur.execute("commit;")
                    await conn.commit()
                except Exception as err:
                    await conn.rollback()
                    raise err
       	cls.pool = None

    @classmethod
    async def select(cls, sql, params=None, one=True):
        params = params or []
        await cls.get_pool()
        async with cls.pool.acquire() as conn:
            async with conn.cursor() as cur:
                try:
                    await cur.execute(sql, params)
                    return await (cur.fetchone() if one else cur.fetchall())
                except Exception as err:
                    conn.rollback()
                    raise err

2893 次点击
所在节点    Python
7 条回复
janxin
2019-03-21 00:25:00 +08:00
考虑过脏读幻读问题么
nightstart
2019-03-21 01:00:01 +08:00
@janxin 幻读脏读应该是在并发比较大的情况下出现的吧。 我的操作是顺序操作 比如上面插入了一条记录 然后紧接着下一个操作是去把这条记录通过条件读出来 然后就遇到了这种情况
Trim21
2019-03-21 01:47:34 +08:00
我试了一下没法复现...
https://gist.github.com/Trim21/b5f77e819d7fdc0ccd1364c2f563ab4e

你具体调用这个库的代码和 Config.mysql 是什么样的
pynix
2019-03-21 03:00:36 +08:00
估计你没理解 aio
GTim
2019-03-21 08:09:52 +08:00
@pynix 同意楼上,你用同步思维的方式来写异步代码,insert 还没执行完的时候,select 就开始执行了,那就没数据了
nightstart
2019-03-22 18:56:40 +08:00
@Trim21 你好我弄了一个 demo 能百分百复现问题的 但是 V2EX 的帖子无法编辑 ....
nightstart
2019-03-22 18:57:24 +08:00
```
# -*- coding: utf-8 -*-
import time
import asyncio
from app.utils.aiomyob import AioMysqlHelper

async def select():
for _ in range(10):
await asyncio.sleep(1)
print(await AioMysqlHelper.select("SELECT * FROM test", one=False))

async def main():
await asyncio.gather(*[select() for _ in range(1)])

if __name__ == "__main__":
start = time.time()
loop = asyncio.get_event_loop()
loop.run_until_complete(AioMysqlHelper.init_pool())
loop.run_until_complete(main())
loop.close()
print(time.time() - start)
```

先在数据库里面手动插入一条数据
在十次 print 的过程中 挑个时间在数据库中手动执行 delete from test;
输出是这样的

```
[{'id': 24, 'name': 'wwww'}]
[{'id': 24, 'name': 'wwww'}]
[{'id': 24, 'name': 'wwww'}]
[{'id': 24, 'name': 'wwww'}]
()
[{'id': 24, 'name': 'wwww'}]
[{'id': 24, 'name': 'wwww'}]
[{'id': 24, 'name': 'wwww'}]
[{'id': 24, 'name': 'wwww'}]
()
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/546790

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX