我正在追踪一个大型商业应用程序中的错误,其中业务流程失败但部分保留在数据库中。让事情更难以弄清楚的是,每隔几周流程才会失败一次,在每次失败之间都成功处理了数十万个流程。当并发/工作进程数量增加时,错误频率似乎会提高。
到目前为止,我们已经能够使用此程序重现所见到的问题。(.NET 4.7.1框架)
我们的生产代码没有显式调用
到目前为止,我们已经能够使用此程序重现所见到的问题。(.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
能够正常工作的情况下进行crud操作。
更新1
我不想要的“回滚”是由.Net连接共享机制中某处的bug引起的。该bug在所有.Net Framework版本(4.5.1至4.8)以及新的System.Data.SqlClient package上都可以重现。
Transaction.Current.TransactionInformation.Status
属性直到程序失败之前都是Active
。 - stalskal