Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用asyncio和postgres在python中进行事务处理?_Python_Postgresql_Transactions_Async Await_Python Asyncio - Fatal编程技术网

如何使用asyncio和postgres在python中进行事务处理?

如何使用asyncio和postgres在python中进行事务处理?,python,postgresql,transactions,async-await,python-asyncio,Python,Postgresql,Transactions,Async Await,Python Asyncio,我的RPC方法中有两个操作: async def my_rpc(self, data): async with self.Engine() as conn: await conn.execute("SELECT ... FROM MyTable"); ... # It seems the table MyTable can be changed by another RPC await conn.execute("UPDATA MyTab

我的RPC方法中有两个操作:

async def my_rpc(self, data):
    async with self.Engine() as conn:
        await conn.execute("SELECT ... FROM MyTable");
        ...  # It seems the table MyTable can be changed by another RPC
        await conn.execute("UPDATA MyTable ...");
另一个RPC方法可以在执行“my_RPC”操作之前(在两次等待SQL查询之间)更改数据库。如何避免这种情况

self.Engine代码(使用Engineaiopg.sa.create\u Engine调用):


看起来避免混淆的唯一方法是让每个事务在一个单独的数据库连接中进行(Python端游标不会这样做) 实现这一点的方法是拥有一个连接池,并让引擎方法为每个“异步线程”提供不同的连接


如果Postgresql本身的连接器是异步感知的(顺便说一句,您使用的是哪个驱动程序?)。或者它上面的数据库包装层。如果不是,您必须自己实现这个连接池。我认为Sqlalchemy连接池在这种情况下可以正常工作,因为独立于在协同例程中使用,连接只会在
async with
块的末尾被释放

首先,
aiopg
在自动提交模式下工作,这意味着您必须在手动模式下使用事务

其次,对于在第一条语句中读取的锁行,必须使用SELECTFORUPDATE。选择更新锁定,在事务完成之前选择行


你能为self.Engine显示你的代码吗?@jsbueno我添加了代码我还没有测试我的代码。但也有与“aiopg.sa”分开使用的连接。也许这正是我需要的?是的。由于您正在通过
async with
中的调用获取连接,并使用一个为asyncio准备好的连接器,所以您应该只需要这些。我认为并非所有。。。您必须手动使用事务并选择更新
class ConnectionContextManager(object):
    def __init__(self, engine):
        self.conn = None
        self.engine = engine

    async def __aenter__(self):
        if self.engine:
            self.conn = await self.engine.acquire()
            return self.conn

    async def __aexit__(self, exc_type, exc, tb):
        try:
            self.engine.release(self.conn)
            self.conn.close()
        finally:
            self.conn = None
            self.engine = None
async def my_rpc(self, data):
    async with self.Engine() as conn:
        await conn.execute("BEGIN")
        await conn.execute("SELECT ... FROM MyTable WHERE some_clause = some_value FOR UPDATE")
        ...  # It seems the table MyTable can be changed by another RPC
        await conn.execute("UPDATE MyTable SET some_clause=...")
        await conn.execute("""COMMIT""")