【问题标题】:transaction() doesn't increment @@TRANCOUNT?事务()不增加@@TRANCOUNT?
【发布时间】:2018-05-01 09:39:49
【问题描述】:

MS SQL SERVER 2008。Qt + ODBC。

我正在尝试通过回滚最高级别的事务来回滚数据库中的一些更改(在内部进行的)。但看起来我的第二个 db.transaction() 调用没有增加 @@TRANCOUNT 并且第一次提交(内部)完全关闭事务。因此,外部事务级别的下一个回滚命令就被忽略了。

一些例子。每次操作后,注释字符串显示从 DB 收到的 @@TRANCOUNT:

db.transaction();                                       //@@TRANCOUNT = 0
query->exec("INSERT INTO TestOnly (Value) VALUES('1')");//@@TRANCOUNT = 1
db.transaction();                                       //@@TRANCOUNT = 1
query->exec("INSERT INTO TestOnly (Value) VALUES('2')");//@@TRANCOUNT = 1
db.commit();                                            //@@TRANCOUNT = 0
query->exec("INSERT INTO TestOnly (Value) VALUES('3')");//@@TRANCOUNT = 0
db.rollback();                                          //@@TRANCOUNT = 0

测试代码:

...
db = QSqlDatabase::addDatabase("QODBC3");
...
query = new QSqlQuery(db);
...

bool ok;
ok = db.transaction(); qDebug() << "Start transaction" << " result = " << ok << "; errorText: " << db.lastError().text();
PrintTranCount(); //0

query->exec("INSERT INTO TestOnly (Value) VALUES('1')");
PrintTranCount(); //1

ok = db.transaction(); qDebug() << "Start transaction" << " result = " << ok << "; errorText: " << db.lastError().text();
PrintTranCount(); //2

query->exec("INSERT INTO TestOnly (Value) VALUES('2')");
PrintTranCount(); //3

ok = db.commit(); qDebug() << "Commit transaction" << " result = " << ok << "; errorText: " << db.lastError().text();
PrintTranCount(); //4

query->exec("INSERT INTO TestOnly (Value) VALUES('3')");
PrintTranCount(); //5

ok = db.rollback();  qDebug() << "Rollback transaction" << " result = " << ok << "; errorText: " << db.lastError().text();
PrintTranCount(); //6

调试输出:

Start transaction  result =  true ; errorText:  " "  
Transaction Count   0: 0  
Transaction Count   1: 1   
Start transaction  result =  true ; errorText:  " "   
Transaction Count   2: 1   
Transaction Count   3: 1   
Commit transaction  result =  true ; errorText:  " "  
Transaction Count   4: 0  
Transaction Count   5: 0   
Rollback transaction  result =  true ; errorText:  " "  
Transaction Count   6: 0   

PrintTranCount() 函数:

static int Num = 0;
query->exec("SELECT @@TRANCOUNT");query->first();
qDebug() << "Transaction Count  "<< Num << ": " <<query->value(0).toInt();
Num++;

第二次交易后交易计数器 (@@TRANCOUNT) 没有增加到 2 有什么原因吗?我没有正确理解事务计数器的概念?还是数据库/驱动程序设置有问题?也许我的示例代码中有一些我错过的错误?

如有任何提示,我将不胜感激。对不起谷歌翻译:)

【问题讨论】:

  • SQL Server 中没有嵌套事务,因为任何“内部”事务的提交都不会提交任何内容(仅增加 @@trancount),任何“内部”回滚都会回滚。
  • 请阅读这里:sqlskills.com/blogs/paul/…
  • 对不起,我没有正确描述问题。在我的情况下(上面描述的 '1' '2' '3' 插入)根本没有任何回滚操作。根据您评论中的一篇文章,外部回滚应该取消在内部事务中提交的操作。但这不会发生。我在 TestOnly 表中有所有三行。我决定立即询问事务计数器,因为看起来数据库根本没有启动内部事务。
  • 我不知道你的编程语言,但如果你使用 T-SQL 并编写 3 个这样的插入: INSERT INTO TestOnly (Value) VALUES('1'); INSERT INTO TestOnly (Value) VALUES('2');INSERT INTO TestOnly (Value) VALUES('3') 会有三个事务,SQL Server 以自动提交模式运行
  • 要在一个事务中获取所有这些,您应该显式打开事务:BEGIN TRAN INSERT INTO TestOnly (Value) VALUES('1');插入TestOnly(值)VALUES('2');插入TestOnly(值)VALUES('3');提交

标签: sql-server database qt transactions


【解决方案1】:

查看源代码解决了所有问题

db.transaction() 不会向数据库发送任何“开始传输”命令(至少使用 ODBC 驱动程序)。此函数仅将提交模式更改为“manual commit mode”。之后,首先 db.commit() 确认所有更改(通过发送“SQLEndTran”命令)并再次将模式更改回“自动提交模式”。

要使用@@TRANCOUNT 的“嵌套”(不是真正的嵌套)事务,手动向数据库发送“tran begin”/“commit”/“rollback”命令就足够了。在我的例子中:

query->exec("begin tran");                              //@@TRANCOUNT = 1
query->exec("INSERT INTO TestOnly (Value) VALUES('1')");//@@TRANCOUNT = 1
query->exec("begin tran");                              //@@TRANCOUNT = 2
query->exec("INSERT INTO TestOnly (Value) VALUES('2')");//@@TRANCOUNT = 2
query->exec("commit");                                  //@@TRANCOUNT = 1
query->exec("INSERT INTO TestOnly (Value) VALUES('3')");//@@TRANCOUNT = 1
query->exec("rollback");                                //@@TRANCOUNT = 0

【讨论】:

    猜你喜欢
    • 2019-09-19
    • 1970-01-01
    • 2014-09-26
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 2019-11-06
    • 2014-05-24
    • 1970-01-01
    相关资源
    最近更新 更多