如何检测回滚已经发生?
How to detect that rollback has occurred?
我正在寻找大型业务应用程序中的一个错误,其中业务流程失败但部分保留到数据库中。更难弄清楚的是,这个过程每隔几周就会失败一次,每次失败之间都会成功处理数十万次。当工作进程的 concurrency/number 增加时,错误频率似乎会增加。
到目前为止,我们已经能够通过该程序重现我们所看到的内容。 (.NET 4.7.1 框架)
using (var transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
using (var sqlConnection = new SqlConnection("Server=localhost;Database=Database1;Trusted_Connection=True"))
{
sqlConnection.Open();
// Doing some unwanted nested manual transaction and rolling it back
var transaction = sqlConnection.BeginTransaction();
new SqlCommand($"INSERT INTO TestTable VALUES('This will be rolled back}')", sqlConnection).ExecuteNonQuery();
transaction.Rollback();
// Now doing some work with the DB.
// You might expect it to become a part of transactionScope, but that is NOT the case!
// So this command will actually succeed, with data written to the DB.
new SqlCommand($"INSERT INTO TestTable VALUES('This will be inserted')", sqlConnection).ExecuteNonQuery();
// Doing something which promotes the local transaction to a distributed transaction.
using (var sqlConnection2 = new SqlConnection("Server=localhost;Database=Database2;Trusted_Connection=True"))
{
// The program will fail here, with message "The transaction has aborted, Failure while attempting to promote transaction."
sqlConnection2.Open();
new SqlCommand($"INSERT INTO TestTable2 VALUES('We will never come this far')", sqlConnection2).ExecuteNonQuery();
}
}
transactionScope.Complete();
}
我们的生产代码没有明确调用 transaction.Rollback()
,在我的示例中它只是作为重现错误消息和行为的手段。但是,如果我们的任何第三方库进行此调用,我想尽快抛出异常并退出。最好在应用层。
我怎样才能检测到对 Rollback()
的调用已经完成?我真的不想在不确定 transactionScope
是否能够完成其工作的情况下进行粗略操作。
更新 1
我不需要的 "rollback" 是由 .Net 的连接共享机制中某处的错误引起的。该错误在 4.5.1 和 4.8 之间的所有 .Net Framework 版本以及新的 System.Data.SqlClient package.
上重现
一个issue has been added to the System.Data.SqlClient repository.
不同的交易 API 不能一起工作。所以你在这里处于危险区域。
How can I detect that the call to Rollback() has been made?
select @@trancount
应该总是告诉你。回滚会将 @@trancount 恢复为 0。
我正在寻找大型业务应用程序中的一个错误,其中业务流程失败但部分保留到数据库中。更难弄清楚的是,这个过程每隔几周就会失败一次,每次失败之间都会成功处理数十万次。当工作进程的 concurrency/number 增加时,错误频率似乎会增加。
到目前为止,我们已经能够通过该程序重现我们所看到的内容。 (.NET 4.7.1 框架)
using (var transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
using (var sqlConnection = new SqlConnection("Server=localhost;Database=Database1;Trusted_Connection=True"))
{
sqlConnection.Open();
// Doing some unwanted nested manual transaction and rolling it back
var transaction = sqlConnection.BeginTransaction();
new SqlCommand($"INSERT INTO TestTable VALUES('This will be rolled back}')", sqlConnection).ExecuteNonQuery();
transaction.Rollback();
// Now doing some work with the DB.
// You might expect it to become a part of transactionScope, but that is NOT the case!
// So this command will actually succeed, with data written to the DB.
new SqlCommand($"INSERT INTO TestTable VALUES('This will be inserted')", sqlConnection).ExecuteNonQuery();
// Doing something which promotes the local transaction to a distributed transaction.
using (var sqlConnection2 = new SqlConnection("Server=localhost;Database=Database2;Trusted_Connection=True"))
{
// The program will fail here, with message "The transaction has aborted, Failure while attempting to promote transaction."
sqlConnection2.Open();
new SqlCommand($"INSERT INTO TestTable2 VALUES('We will never come this far')", sqlConnection2).ExecuteNonQuery();
}
}
transactionScope.Complete();
}
我们的生产代码没有明确调用 transaction.Rollback()
,在我的示例中它只是作为重现错误消息和行为的手段。但是,如果我们的任何第三方库进行此调用,我想尽快抛出异常并退出。最好在应用层。
我怎样才能检测到对 Rollback()
的调用已经完成?我真的不想在不确定 transactionScope
是否能够完成其工作的情况下进行粗略操作。
更新 1
我不需要的 "rollback" 是由 .Net 的连接共享机制中某处的错误引起的。该错误在 4.5.1 和 4.8 之间的所有 .Net Framework 版本以及新的 System.Data.SqlClient package.
上重现一个issue has been added to the System.Data.SqlClient repository.
不同的交易 API 不能一起工作。所以你在这里处于危险区域。
How can I detect that the call to Rollback() has been made?
select @@trancount
应该总是告诉你。回滚会将 @@trancount 恢复为 0。