V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
nightstart
V2EX  ›  Python

Python aiomysql 我遇到的异常情况

  •  
  •   nightstart · 2019-03-20 23:18:09 +08:00 · 3065 次点击
    这是一个创建于 2079 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    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
    
    
    7 条回复    2019-03-22 18:57:24 +08:00
    janxin
        1
    janxin  
       2019-03-21 00:25:00 +08:00 via iPhone
    考虑过脏读幻读问题么
    nightstart
        2
    nightstart  
    OP
       2019-03-21 01:00:01 +08:00
    @janxin 幻读脏读应该是在并发比较大的情况下出现的吧。 我的操作是顺序操作 比如上面插入了一条记录 然后紧接着下一个操作是去把这条记录通过条件读出来 然后就遇到了这种情况
    Trim21
        3
    Trim21  
       2019-03-21 01:47:34 +08:00
    我试了一下没法复现...
    https://gist.github.com/Trim21/b5f77e819d7fdc0ccd1364c2f563ab4e

    你具体调用这个库的代码和 Config.mysql 是什么样的
    pynix
        4
    pynix  
       2019-03-21 03:00:36 +08:00
    估计你没理解 aio
    GTim
        5
    GTim  
       2019-03-21 08:09:52 +08:00
    @pynix 同意楼上,你用同步思维的方式来写异步代码,insert 还没执行完的时候,select 就开始执行了,那就没数据了
    nightstart
        6
    nightstart  
    OP
       2019-03-22 18:56:40 +08:00
    @Trim21 你好我弄了一个 demo 能百分百复现问题的 但是 V2EX 的帖子无法编辑 ....
    nightstart
        7
    nightstart  
    OP
       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'}]
    ()
    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1076 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 22:33 · PVG 06:33 · LAX 14:33 · JFK 17:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.