【问题标题】:Transaction commit executes succesfully but not getting done事务提交成功执行但未完成
【发布时间】:2009-06-28 15:54:47
【问题描述】:

我在 Sql Server 中遇到了一个奇怪的问题。 我有一个袖珍 PC 应用程序,它连接到 Web 服务,而 Web 服务又连接到数据库并插入大量数据。 Web 服务为连接到它的每台袖珍电脑打开一个事务。每天中午 12 点,有 15 到 20 个人使用不同的掌上电脑同时连接到 Web 服务并成功完成传输。 但在那之后,还有一个与 4000 个独占锁相关联的打开事务(在 Activity Monitor 中可见)。几个小时后,它们消失了(可能是超时了),并且一些传输的数据被删除。有没有办法可以防止这些锁发生?还是以编程方式识别它们并等待解锁?

非常感谢。

【问题讨论】:

    标签: c# sql-server-2005 ado.net transactions


    【解决方案1】:

    您可以运行sp_lock 并检查您感兴趣的表上是否持有任何排他锁。这将告诉您违规连接的SPID,您可以使用sp_whosp_who2查找有关该 SPID 的更多信息。

    或者,Management Studio 中的活动监视器将为您提供此信息的图形版本,并且还允许您终止任何有问题的进程(kill 命令将允许您在查询编辑器中执行相同操作)。

    【讨论】:

    • 谢谢。我不得不等到它再次发生——现在。正如 Active Monitor 所示,有一个与进程相关联的打开事务。使用 sp_lock,我看到这个 SPID 大约有 7000 个锁。是不是异常?如果是这样,我该如何预防?或者有没有办法可以提交这个交易?因为杀死它不是我的问题的选择。再次感谢。
    • 锁的数量相当多!您要注意的是排他锁,标记为 X,因为它们会阻止对底层资源的所有访问。 (IX,意图锁,阻止其他人获得父对象的锁;如果此进程在某行上有 X 锁,则包含该行的页和表被 IX 锁定)。至于贪婪进程,请查看 sp_who2 以了解它从哪里连接,以及应用程序是什么。这应该有助于调试。然后,您可以使用 SQL Profiler 等其他技术来微调调试。
    • 其中 72 个是 IX,所有其他都是 X。如 sp_who2 所示,它来自我的 Web 服务用户,它表示状态为“睡眠”。我上次调试过我的代码,我确信没有例外。执行每次插入后,我可以/应该以编程方式检查任何信息吗?我可以以任何方式配置事务以避免这些锁定吗?
    • 1) 您可以检查的信息:如果您愿意,可以在每次操作后读取一个@@trancount 变量,用于调试信息。 2)您可以配置不支持锁的不同事务隔离级别,但相信我,您不想在这里这样做!
    • 1) @@TRANCOUNT 即使现在也返回 0。你的意思是如果它大于0,我应该等待吗?恐怕它可能会使我的网络服务超时。 2)我不是故意忽略锁,我问是否有办法防止它们发生。
    【解决方案2】:

    您可以使用SQL Server Profiler 来监控发生的语句,包括事务的开始和结束。 Microsoft 支持还提供了一些很棒的工具,因为它们运行分析器和阻止脚本。我正在寻找是否可以找到这些会更新,如果我这样做/。

    如果你有一个打开的事务,你应该能够在活动监视器中看到它,这样你就可以在重新启动服务器之前检查是否有任何打开的事务。

    编辑

    听起来这个问题每天大约在同一时间发生。您需要在问题发生之前将其打开。

    【讨论】:

    • 谢谢。但是,在事务开始后开始跟踪时,Profiler 不会显示任何活动。
    • 没错。我今天早上开始追踪,我正在浏览它以寻找一些奇怪的东西,或者关于锁的东西。你知道我应该检查什么吗?
    【解决方案3】:

    我怀疑你在代码中做错了什么,你是否将命令超时设置为足够大的值来完成他们的工作,或者可能是一个错误正在跳过 COMMIT?

    您可以通过运行检查哪些事务处于打开状态:

    DBCC OPENTRAN
    

    【讨论】:

    • 我没有更改命令超时,并且我确定提交已执行(因为我一次提交了 3 个事务,一个在 MySql 中,一个在 SqlServer 中,另一个在 SqlCE 中;另一个提交了两个事务,我可以看到数据)。 DBCC OPENTRAN 在提交后显示一个打开的事务。我只是不知道现在该怎么做才能承诺。
    • 你能把你的代码删减,小到可以贴在这里吗?
    • //所有方法都由webservice调用,webservice是从一个SqlCE事务里面的一个设备项目调用的 public DataService() { mySqlService = new mySqlService();连接 = 新的 SqlConnection(connectionString);连接.打开();事务 = 连接.BeginTransaction(); } ... // 传输数据的方法——它们使用事务 public void Commit() { transaction.Commit(); mySqlService.Commit();连接。关闭(); } public void Rollback() { transaction.Rollback(); mySqlService.Rollback(); }
    【解决方案4】:

    您选择的超时表明事务仍处于打开状态,并且至少在表的一部分上被锁定。

    您如何通过 Web 服务进行交易?您在代码中如何/在何处提交事务?

    【讨论】:

    • 我正在使用 System.Data.SqlClient。我有一个由袖珍 PC 调用的 WebMethod,它启动事务、插入数据并提交。整个方法在一个 try/catch 块中,如果出现任何异常,它会回滚事务。我回答你的问题了吗?
    • 对不起!我错了。我正在使用 MyGeneration.doodads(我为我的 SqlCe 数据库使用 .Net 提供程序)。 doodads 有一个处理事务的 TransactionMgr。我今天将整个代码更改为使用 .Net Sql 提供程序,看看是否有任何变化。
    【解决方案5】:

    做了很多测试,我发现发生了死锁。但是我找不到原因,因为我只是在一些独立的表中插入了这么多记录。 这些链接有点帮助,但没有运气:

    http://support.microsoft.com/kb/323630

    http://support.microsoft.com/kb/162361

    我什至将我的交易拆分为较小的交易,但我仍然陷入僵局。我终于删除了事务并将代码更改为不从源数据库中删除它们,并且不再出现死锁。

    作为一个教训,现在我知道如果您同时在同一个数据库上执行一些(多个)大型事务,那么您肯定会在 SQL Server 中遇到问题,我不了解 Oracle。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-22
      • 2012-09-03
      • 1970-01-01
      • 1970-01-01
      • 2018-09-06
      • 1970-01-01
      • 2019-10-31
      • 2018-03-25
      相关资源
      最近更新 更多