SQL Server锁定在Python中无法读取和更新的行

SQL Server锁定在Python中无法读取和更新的行,python,sql-server,concurrency,locking,Python,Sql Server,Concurrency,Locking,我需要在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};'

我需要在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()
怎么了? 该代码基于以下内容:
谢谢

因为前两条语句不是在修改数据,否则它在事务结束之前都不会持有锁,而不管是什么

但是您可以在一条语句中完成所有操作,这里不需要
UPDLOCK
,也不需要显式事务(该语句在事务中运行)

更新顶部(1)q
设置BQ_状态=‘加载’
输出inserted.Id、inserted.GCS\u路径、inserted.file\u首次上传
来自dbo。[Queue]作为q,带有(可序列化,行锁)
其中q.[BQ_status]为空,q.upload_date不为空;
虽然
SERIALIZABLE
有时确实只接受共享
S
锁,但这仅适用于
SELECT
或DML语句中未修改的联接表

在本例中,由于
Queue
是正在修改的表,因此在查找正确的行时会执行
U
锁定,这将禁止
U
锁定其他事务,这些事务将在等待时被阻止(仅执行
SELECT
的事务不会被阻止)。然后,当一行即将被修改时,
U
锁被升级为
X
,并被修改


因此,这里不必担心竞争条件,也不必使用
UPDLOCK
提示。

帮自己一个大忙,在SQLSERVER上的存储过程中使用TRY-CATCH和回滚来处理此事务。在seconds语句中,我不仅需要返回ID,还需要返回名为GCS_path、file_first_upload的字段,这些字段稍后将在python程序中使用。为什么需要试一试?(如果我在不存在ID的情况下运行此事务,它将按预期工作(它不执行任何操作)),然后使用第一个select语句执行该操作。只需为GCS_path声明变量,首先上传文件,并捕获其中的值,以便稍后在python程序中重用。删除第二个select语句。谢谢。这很有效。但据我所知,Serializable创建了一个共享锁,所以其他进程仍然可以读取该行,还是我错了?我认为为了避免竞争条件,锁应该是独占锁而不是共享锁。不,这只适用于未修改的表,否则将使用
U
锁,这将阻止其他修改器。除非修改表,否则不能强制执行
X
锁定。已经澄清。