python - 如何使用 asyncio 和 postgres 在 python 中进行交易?

标签 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 MyTable ...");

另一个 RPC 方法可以在操作“my_rpc”完成之前更改数据库(在两次等待 SQL 查询之间)。如何避免这种情况?

self.Engine代码(调用引擎aiopg.sa.create_engine):

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

最佳答案

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

其次,您必须对您在第一条语句中读取的锁定行使用 SELECT FOR UPDATE。 SELECT FOR UPDATE 锁定选择的行,直到事务完成。 Read more details .

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""")

关于python - 如何使用 asyncio 和 postgres 在 python 中进行交易?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38702756/

相关文章:

python - 将 psql 类型 oid 映射到 python 类型 - 使用 psycopg2

sql - Postgres 一次更新多行

java - 什么时候是使用应用服务器的合适时机?

java - hibernate/Ehcache : evicting collections from 2nd level cache not synchronized with other DB reads

python - 如何防止内置类型被覆盖(分配给)它们的方法?

java - 将 python 字典转换为 Java hashmap,其中值类型是数据结构和 lambda 函数的混合

sql - 有条件的聚合?

rest - GetTransactionDetails Paypal

python - scikit-learn 分割数据集中的随机状态

python - 当用户导入已弃用的变量时引发自定义 ImportError