sách gpt4 ai đã đi

c# - 解决 SQL 事务超时的防弹方法

In lại 作者:行者123 更新时间:2023-11-30 15:20:08 25 4
mua khóa gpt4 Nike

最近我们遇到了一个非常有趣的问题,它与 SQL 事务超时有关。出于问题的考虑,超时的语句并不重要,但它是单个 INSERT 语句,没有显式事务,客户端生成的 GUID 作为键:

INSERT MyTable
(id, ...)
VALUES (, ...)

我们还有一个就地重试策略,因此如果命令因 SqlException 而失败,则会重试。 SQL Server (Azure SQL) 有一天没有正常运行,我们在重试期间遇到了很多奇怪的 PK 违规错误。它们是由 重试 实际上成功提交 SQL Server 事务引起的(因此导致使用已获取的 ID 进行插入)。我知道 SQL 超时是 purely client side concept ,所以如果客户端认为 SqlCommand 失败了 - 它可能是也可能不是是这个意思。

我怀疑客户端显式事务控制(例如,如下所示使用 TransactionScope 包装语句)将解决 99% 的此类问题——因为 Commit 实际上是非常快速且廉价的操作。但是,我仍然看到那里的警告——超时也可能发生在提交阶段。应用程序可能再次处于无法猜测事务是否真正提交的情况(以确定重试的必要性)。

问题是如何以防弹(针对此类麻烦)和通用方式编写代码,并且仅在确定事务未提交时才重试。

using (var trx = new TransactionScope())
using (var con = GetOpenConnection(connectionString))
{
con.Execute("");

// what if Complete() times out?!
// to retry or not to retry?!
trx.Complete();
}

1 Câu trả lời

问题是异常并不意味着交易失败。对于任何补偿操作(如重试),您需要有明确的方法来判断它是否失败。我的建议存在可扩展性问题,但技术才是最重要的,可扩展性问题可以通过其他方式解决。

我的解决方案;

  1. COMMIT 之前的最后一个 INSERT 是将 Guid 写入跟踪表。
  2. 如果发生异常,表明网络故障,SELECT @@TRANCOUNT。如果它表明您仍在交易中(大于 0)(这可能永远不会发生,但值得检查)那么您可以愉快地重新提交您的 COMMIT
  3. 如果@@TRANCOUNT 返回 0,则您不再处于事务中。从跟踪表中选择您的 Guid 将告诉您您的 COMMIT 是否成功。
  4. 如果您的提交不成功(@@TRANCOUNT ==0 并且您的 Guid 不在跟踪表中),则重新提交从 BEGIN TRANSACTION 开始的整个批处理。

关于c# - 解决 SQL 事务超时的防弹方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40727012/

25 4 0
Bài viết được đề xuất: c# - 项目中不存在目标 "GetCopyToPublishDirectoryItems"。
Bài viết được đề xuất: c# - 泛型类型相互引用
Bài viết được đề xuất: c# - MissingMethodException DbSet.ToList 异常
Bài viết được đề xuất: c# - 如何将用户输入注册到列表 C#
行者123
Hồ sơ cá nhân

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá Didi Taxi miễn phí
Mã giảm giá Didi Taxi
Giấy chứng nhận ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com