Pyodbc - 确定是否有任何事务处于挂起状态并且需要提交

时间:2015-12-11 08:20:30

标签: python odbc pyodbc

我正在使用pyodbc进行自动提交'设为false。 我假设如果只使用SELECT个sql语句(没有INSERTUPDATE),那么调用' commit'函数对DB无效。

如果我不打电话给#t;提交&#39>,pyodbc中是否有任何方法可以确定是否有任何未决的更改会丢失?

我一直在考虑使用pyodbc' getinfo'函数是SQLGetInfo的包装器,但无法为其找到任何合适的参数。

实际上我想要做的只是通知用户数据库中的数据将被更改,但我不想控制使用的SQL语句(仅SELECT或者也是UPDATE& INSERT)因为有太多地方我需要检查它。

1 个答案:

答案 0 :(得分:2)

不幸的是,pyodbc没有内置功能来检查未决的提交。

在SQL Server(从2008年开始)中,您可以使用database_transaction_state表中的sys.dm_tran_database_transactions字段在数据库级别检查挂起的提交。带有暂挂提交的事务状态应为4。没有等待提交的人应该是3

documentation中,提到的状态定义为:

  

3 =事务已初始化,但未生成任何日志   记录。

     

4 =交易已生成日志记录。

以下脚本检查了这个想法。

输出

Starting point, no pending transaction or commits
    @@TRANCOUNT = 0
    database_transaction_state = None
Disable autocommit
    @@TRANCOUNT = 1
    database_transaction_state = 3
Perform an Insert
    @@TRANCOUNT = 1
    database_transaction_state = 4
Explicit commit
    @@TRANCOUNT = 1
    database_transaction_state = 3
Enable autocommit
    @@TRANCOUNT = 0
    database_transaction_state = None

代码

import pyodbc

conn_param = {
    "DRIVER": "{ODBC Driver 13 for SQL Server}",
    "SERVER": "(localdb)\\ProjectsV13",
    "DATABASE": "master"
}

conn_string = ";".join(["{}={}".format(k, v) for k, v in conn_param.items()])

conn = pyodbc.connect(conn_string, autocommit=True)
cursor = conn.cursor()


def check():
    print("\t@@TRANCOUNT = {}".format(
        cursor.execute("select @@TRANCOUNT").fetchval()
    ))

    print("\tdatabase_transaction_state = {}".format(
        cursor.execute("""
        select database_transaction_state
        from sys.dm_tran_database_transactions 
        where transaction_id = CURRENT_TRANSACTION_ID() 
        and database_id = (
            select dbid from sys.sysprocesses where spid = @@SPID
        )""").fetchval()
    ))


cursor.execute("DROP TABLE IF EXISTS testTable")
cursor.execute("SELECT * INTO testTable FROM (VALUES (1), (2), (3)) as x(a)")

print("Starting point, no pending transaction or commits")
check()

print("Disable autocommit")
conn.autocommit = False
check()

print("Perform an Insert")
cursor.execute("INSERT INTO testTable VALUES (4)")
check()

print("Explicit commit")
conn.commit()
check()

print("Enable autocommit")
conn.autocommit = True
check()

cursor.execute("DROP TABLE IF EXISTS testTable")
cursor.close()
conn.close()