【发布时间】:2021-08-09 03:21:09
【问题描述】:
对于可以同时运行多个进程的程序,我需要在 SQL Server 和 Python 中锁定一行,读取然后更新该行的一个字段,以避免竞争条件。
我正在使用以下代码,但在 Python 中,它会更新一个 Id(即 3411)并返回另一个 Id(即 3071)。如果我直接在 SSMS 中运行相同的 SQL 代码,它会更新并返回相同的 Id。
import pyodbc
def read_and_update_files_queue(self):
conn = pyodbc.connect('Driver={SQL Server};'
'Server='+self.server+';'
'Database='+self.database+';'
'Trusted_Connection=yes;')
cursor = conn.cursor()
sql_query=f'''
BEGIN TRANSACTION;
DECLARE @Temp_ID AS INT
SELECT TOP 1 @Temp_ID=Id
FROM dbo.[Queue]
WITH(XLOCK, ROWLOCK)
WHERE [BQ_status] IS NULL and upload_date IS NOT NULL
Select TOP 1
Id,GCS_path,file_first_upload
FROM dbo.[Queue]
WITH(XLOCK, ROWLOCK)
WHERE Id=@Temp_ID
UPDATE dbo.[Queue] SET BQ_status='Loading'
WHERE Id=@Temp_ID
COMMIT TRANSACTION;
'''
cursor.execute(sql_query)
cursor.commit()
怎么了? 代码基于此: In SQL Server, how can I lock a single row in a way similar to Oracle's "SELECT FOR UPDATE WAIT"? 谢谢!!
【问题讨论】:
-
帮自己一个大忙,并在 SQLSERVER 上的存储过程中使用 TRY CATCH WITH A ROLLBACK 处理此事务。另外你用第二个选择语句完成了什么?
-
在秒语句中,我不仅需要返回 ID,还需要返回名为 GCS_path、file_first_upload 的字段,这些字段稍后将在 python 程序中使用。为什么需要try catch? (如果我在不存在 ID 时运行此事务,它会按预期工作(它什么也不做))
-
然后使用您的 First select 语句执行此操作。只需为 GCS_path、file_first_upload 声明变量并捕获其中的值以便稍后在 python 程序中重用。消除第二个 select 语句。
标签: python sql-server concurrency locking