当前位置: 代码迷 >> python >> 如何通过pyodbc在MS SQL Server的2个表上放置范围/表锁
  详细解决方案

如何通过pyodbc在MS SQL Server的2个表上放置范围/表锁

热度:98   发布时间:2023-06-27 21:53:25.0

我现在通过pyodbc同时处理2个表。 在完成处理之前,我想在2个表上放置锁,以便在我完成之前没有人可以更改2个表。 我怎样才能做到这一点?

我尝试了以下操作,但失败并显示错误。

import pyodbc
conn = pyodbc.connect("conn_str")
conn.execute("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;")
conn.execute("begin transaction trans;")
cur1 = conn.execute("select * from tbl1;")
cur2 = conn.execute("select * from tbl2;")
... some processing at cur1 and cur2 at python ...
conn.execute("commit transaction trans;")

但是,执行“ cur2 = conn.execute(“从tbl2; *中选择*)”时会出现以下错误

[Microsoft][ODBC SQL Server Driver]Connection is busy with results for another hstmt (0) (SQLExecDirectW)

我的代码有什么问题吗? 非常感谢您的帮助。

最初,SQL Server ODBC每个连接仅限于一个活动的hstmt (相当于pyodbc.cursor的ODBC)。 稍后,Microsoft将MARS(多个活动结果集)功能添加到SQL Server ODBC,但是默认情况下该功能为“关闭”。

所以这段代码

import pyodbc
import sys

print(f"Python version {sys.version}")  # Python version 3.6.4 ...
print(f"pyodbc version {pyodbc.version}")  # pyodbc version 4.0.24
conn_str = (
    r'DRIVER=ODBC Driver 17 for SQL Server;'
    r'SERVER=.\SQLEXPRESS;'
    r'DATABASE=myDb;'
    r'Trusted_Connection=yes;'
)
cnxn = pyodbc.connect(conn_str, autocommit=True)

cnxn.set_attr(pyodbc.SQL_ATTR_TXN_ISOLATION, pyodbc.SQL_TXN_SERIALIZABLE)
cnxn.autocommit = False  # enable transactions

cur1 = cnxn.execute("SELECT 1 AS x UNION ALL SELECT 2 AS x")
cur2 = cnxn.execute("SELECT 'foo' AS y UNION ALL SELECT 'bar' AS y")

print(cur1.fetchone())
print(cur2.fetchone())
print(cur1.fetchone())
print(cur2.fetchone())

失败于

Traceback (most recent call last):
  File "C:/Users/Gord/PycharmProjects/py3pyodbc_demo/main.py", line 18, in <module>
    cur2 = cnxn.execute("SELECT 'foo' AS y UNION ALL SELECT 'bar' AS y")
pyodbc.Error: ('HY000', '[HY000] [Microsoft][ODBC Driver 17 for SQL Server]Connection is busy with results for another command (0) (SQLExecDirectW)')

但是,如果我们将MARS_Connection=yes添加到连接字符串

conn_str = (
    r'DRIVER=ODBC Driver 17 for SQL Server;'
    r'SERVER=.\SQLEXPRESS;'
    r'DATABASE=myDb;'
    r'Trusted_Connection=yes;'
    r'MARS_Connection=yes;'
)

然后代码工作。

不幸的是,在您的情况下,您使用的是古老的DRIVER=SQL Server ,它太旧了,无法支持MARS_Connection=yes因此您的选择

  • 使用较新版本的SQL Server ODBC驱动程序,或
  • 打开两个单独的连接,每个游标一个。
  相关解决方案