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

时间:2018-09-23 14:43:07

标签: python sql-server pyodbc

我现在通过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(“ select * from tbl2;”)“时出现以下错误

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

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

1 个答案:

答案 0 :(得分:0)

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

这段代码

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驱动程序的较新版本,或者
  • 打开两个单独的连接,每个游标一个。