与 psycopg2 的并发更新
Concurrent updates with psycopg2
在服务器上,我有一个 API 被一个或多个客户端调用。服务器可以几乎同时接收到针对同一个 PostgreSQL 属性的多个更新指令。这些请求并不是同时到达的,我只想一个接一个地执行。因为(Flask)API,我无法控制上一个调用结束,所以新的更新可以在上一个调用完成之前调用。我希望 psycopg2/postgresql 能够对更新进行排队并一个接一个地安静地进行它们(甚至可能不按顺序),但它似乎不是那样工作的。
以下是需要更新时在服务器上调用的函数的简化版本。如果重要的话,要更新的属性是一个 JSONB 对象。因此有 'path' 来确定要更新 JSONB 对象的哪一部分。所以 API 调用看起来像这样:
def pg_update(data, path):
conn = psycopg2.connect(...) # always the same database.
cur = conn.cursor()
# JSONB update for a single selected row and column.
# 'column' and 'select_row' are determined with the parameters 'data' and 'path'.
command = (
f"""UPDATE MY_TABLE SET """
f"""{column} = jsonb_merge({column}, %s) """
f"""WHERE {select_row};"""
)
cur.execute(command, [Json(data)])
conn.commit()
当连续调用两次时,此调用导致错误(在“cur.execute”):
psycopg2.errors.InternalError_: tuple concurrently updated
由于服务器一直保持 运行,我还可以在 API 调用“pg_update”之外定义 conn
,以便所有调用都使用相同的 psycopg2 连接。但是,当为同一属性请求两次更新时,我得到的是:
psycopg2.ProgrammingError: execute cannot be used while an asynchronous query is underway
为了以防万一,我在psycopg2.connect
中强制使用了async_ = False
。没有变化。
总而言之,我如何允许对相同属性进行多次更新,一个接一个,即使这些更新几乎同时来自独立的、不可控制的客户端请求?也许需要锁定机制?排队机制?
您可以使用 SELECT FOR UPDATE mechanism. Here 一些简单的例子,可能会有帮助。
在服务器上,我有一个 API 被一个或多个客户端调用。服务器可以几乎同时接收到针对同一个 PostgreSQL 属性的多个更新指令。这些请求并不是同时到达的,我只想一个接一个地执行。因为(Flask)API,我无法控制上一个调用结束,所以新的更新可以在上一个调用完成之前调用。我希望 psycopg2/postgresql 能够对更新进行排队并一个接一个地安静地进行它们(甚至可能不按顺序),但它似乎不是那样工作的。
以下是需要更新时在服务器上调用的函数的简化版本。如果重要的话,要更新的属性是一个 JSONB 对象。因此有 'path' 来确定要更新 JSONB 对象的哪一部分。所以 API 调用看起来像这样:
def pg_update(data, path):
conn = psycopg2.connect(...) # always the same database.
cur = conn.cursor()
# JSONB update for a single selected row and column.
# 'column' and 'select_row' are determined with the parameters 'data' and 'path'.
command = (
f"""UPDATE MY_TABLE SET """
f"""{column} = jsonb_merge({column}, %s) """
f"""WHERE {select_row};"""
)
cur.execute(command, [Json(data)])
conn.commit()
当连续调用两次时,此调用导致错误(在“cur.execute”):
psycopg2.errors.InternalError_: tuple concurrently updated
由于服务器一直保持 运行,我还可以在 API 调用“pg_update”之外定义 conn
,以便所有调用都使用相同的 psycopg2 连接。但是,当为同一属性请求两次更新时,我得到的是:
psycopg2.ProgrammingError: execute cannot be used while an asynchronous query is underway
为了以防万一,我在psycopg2.connect
中强制使用了async_ = False
。没有变化。
总而言之,我如何允许对相同属性进行多次更新,一个接一个,即使这些更新几乎同时来自独立的、不可控制的客户端请求?也许需要锁定机制?排队机制?
您可以使用 SELECT FOR UPDATE mechanism. Here 一些简单的例子,可能会有帮助。