执行非查询时SqlException'timeout expired',但插入了数据

 云沏-茶 发布于 2022-12-10 17:57

我在负载测试场景下遇到了奇怪的行为:后端(sql server 2012)正在超载并且一些命令超时(这仍然是预期的,因为后端服务器是半故意慢的HW); 但我们的平台定期(越来越延迟)重试超时操作 - 并在几次重试后突然开始接收'无法插入重复键'SqlException.

我验证只能生成具有特定唯一键的单行并尝试插入(第一次插入并且所有可能的重试始终在同一线程上进行).

我还修改了SP,以便它使用显式事务:

BEGIN TRY

    BEGIN TRANSACTION;

    -- Insert into table A

    -- Insert into table B

    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION;
    THROW
END CATCH

但问题仍然存在.

有什么想法可以发生这种情况吗?

如何找出超时的来源(后端与客户端)?

有没有办法确保操作成功完成或失败(基本上是事务 - 但可能来自客户端代码)?

EDIT01: 我认为解决这个问题的一种方法是利用ado.net集成SQL服务器分布式事务 - 例如:

using (TransactionScope scope = new TransactionScope())
{
    //Perform the sql commands

    //if above statements throws (e.g. due to timeout) - than the transaction is not commited and it will be rolled back
    scope.Complete()
}

但是:我同意它只会增加复杂性并且可能仍然反对同一个问题(usr概述的两个将军问题).因此,最好的方法可能是编写客户端和服务器端的代码来依赖这样的选项 - 再次由usr在他的回答中指出

1 个回答
  • 这是预期的行为.当客户端和服务器之间的通信中断时,客户端不知道操作的结果.它可能永远不会被发送,或者它已被发送但未被接收,或者它已收到但失败了,或者它已收到但是成功响应没有通过.

    这是两个将军的问题.它是无法解决的(严格定义时).

    你必须解决它.在插入之前检查是否存在或处理重复键异常.

    或者,只需增加超时.对于最终成功的其他工作命令,中止它对你没有任何好处.中止并重新启动它并不会使它变得更快(除非巧合).超时主要用于网络错误或失控查询(错误).

    2022-12-11 02:06 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有