代码之家  ›  专栏  ›  技术社区  ›  Lex

在什么情况下,来自C应用程序的MSDTC事务的SQL复制会部分(且无提示地)失败

  •  0
  • Lex  · 技术社区  · 16 年前

    我们有一个特别奇怪的问题,让我来说明一下。 找到解决方案,见下文

    我们有三个SQL Server 2005数据库,为便于讨论,称为: 阿尔法 , 贝塔 伽马 .

    这些数据库之间定义了复制关系,如下所示:

    这三个数据库都有一个名为“anexample”的表,具有相同的模式。复制设置为 阿尔法 是提供程序,其他两个数据库是订阅服务器。

    1. 使用msdtc事务(由transactionscope处理)的c.net 3.5应用程序同时读取和写入数据库:alpha和beta。
    2. 此事务中的表“anexample”仅在alpha上更新。
    3. msdtc事务已成功提交。
    4. “anexample”表可能在中更新 阿尔法 而这一变化立即被复制到 伽马
    5. 上未发生更改 贝塔 (探查器确认数据库上没有发生任何活动),SQL日志或事件日志中也没有出现任何错误
    6. 在management studio中使用相同凭据更新“anexample”的查询重新运行成功(复制到 贝塔 发生)
    7. 运行对上另一个表的msdtc事务写入 贝塔 ,然后使用主应用程序dal、连接字符串和配置对alpha的“anexample”表进行完全相同的写入操作也完全成功(复制到 贝塔 发生)

    这使我们相信主应用程序中发生了一些变化,而这些变化并不是孤立地发生的。

    可能的线索/红鲱鱼

    在我们成功的测试和主应用程序使用的实际查询之间,唯一的区别是隔离级别已经有所改变。在成功的查询中,它被设置为事务隔离级别read committed only,而在失败的场景中它被设置为serializable(尽管没有显式调用来更改代码库或存储过程中的隔离级别)。

    我们确实觉得这有点像在management studio中使用这种隔离级别再次成功地运行查询而没有问题。但事实上,这可能是我们尚未发现的另一个问题的征兆,这是不同的观点。

    为了完整起见,下面是无法复制到beta版(但对gamma版)的查询的设置。

    -- network protocol: TCP/IP
    set quoted_identifier on
    set arithabort off
    set numeric_roundabort off
    set ansi_warnings on
    set ansi_padding on
    set ansi_nulls on
    set concat_null_yields_null on
    set cursor_close_on_commit off
    set implicit_transactions off
    set language us_english
    set dateformat mdy
    set datefirst 7
    set transaction isolation level *serializable*
    

    有点像个头巾。

    2 回复  |  直到 8 年前
        1
  •  0
  •   ahains    16 年前

    我假设这是事务复制? 如果是这样,日志读取器将从事务日志中获取对订阅服务器的更改,因此这个问题听起来确实很奇怪。

    我将尝试在发布服务器数据库上运行跟踪,以便您可以查看复制代理的操作。不知道可能出了什么问题,但也许会有什么东西向你扑来。

        2
  •  0
  •   Lex    16 年前

    所以我们找到了问题所在。如上所述;我们有一个分布式事务 阿尔法 然后 贝塔 . 写信给 贝塔 然后成功复制到 伽马 它无法无声地 阿尔法 . 然而,其中一个遗漏是 阿尔法 正在被复制到 贝塔 (大型数据库模式的问题)。将此写入移动到 贝塔 意味着复制突然成功。

    我没有看到它证明,通过分布式事务的更新不能以一种方式复制更多,但公平地说,这是一个有点模糊的问题,它只是通过确保复制表上的所有写入发生在同一数据库上来解决的。

    希望这能帮助别人。