如何通过 pyodbc 在 MS SQL 服务器的 2 个表上放置 range/table 锁
How to place range/table lock at 2 tables at MS SQL server via 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;")"时出现如下错误"=14=]
[Microsoft][ODBC SQL Server Driver]Connection is busy with results for another hstmt (0) (SQLExecDirectW)
我的代码有什么问题吗?非常感谢您的帮助。
最初,SQL 服务器 ODBC 被限制为每个连接一个活动 hstmt
(相当于 pyodbc.cursor
的 ODBC)。后来,Microsoft 在 SQL Server ODBC 中添加了 MARS(Multiple Active Result Sets)功能,但该功能默认为 "off"。
所以这段代码
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;'
)
然后代码就可以工作了。
不幸的是,在您的情况下,您使用的是太旧而无法支持 MARS_Connection=yes
的古老 DRIVER=SQL Server
,因此您的选择是
- 使用较新版本的 SQL 服务器 ODBC 驱动程序,或者
- 打开两个单独的连接,每个游标一个。
我现在用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;")"时出现如下错误"=14=]
[Microsoft][ODBC SQL Server Driver]Connection is busy with results for another hstmt (0) (SQLExecDirectW)
我的代码有什么问题吗?非常感谢您的帮助。
最初,SQL 服务器 ODBC 被限制为每个连接一个活动 hstmt
(相当于 pyodbc.cursor
的 ODBC)。后来,Microsoft 在 SQL Server ODBC 中添加了 MARS(Multiple Active Result Sets)功能,但该功能默认为 "off"。
所以这段代码
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;'
)
然后代码就可以工作了。
不幸的是,在您的情况下,您使用的是太旧而无法支持 MARS_Connection=yes
的古老 DRIVER=SQL Server
,因此您的选择是
- 使用较新版本的 SQL 服务器 ODBC 驱动程序,或者
- 打开两个单独的连接,每个游标一个。