【问题标题】:ID-ing Deadlocks in a Thread using Firebird使用 Firebird 识别线程中的死锁
【发布时间】:2008-09-15 13:36:02
【问题描述】:

开发人员正在寻找最佳方法来识别特定线程内特定事务的死锁。我们遇到了死锁错误,但这些在 FB 2.0 中非常普遍

发生死锁并导致客户端和数据库之间的数据库连接中断。

  • 我们将实时(每秒一次)数据发送到数据库。
  • 我们打开一个包含大约 30 个线程的线程池,并使用它们来摄取数据(大约每秒 1-2 kB)。
  • 有时数据库只能占用这么多,以至于我们使用池中的下一个线程来尽可能保持流最新。

除了达到最大线程数和中断连接之外,有时还会产生死锁。

因此,我们真的需要就这是否是每秒摄取这么多数据的最佳方法提出意见。我们有多达 100 个这些客户端同时访问数据库。
平均每天的交易量约为 1.5 到 180 万。

【问题讨论】:

    标签: database multithreading deadlock firebird pool


    【解决方案1】:

    我不知道识别特定线程或语句的具体方法。我不得不多次处理 FB 死锁。您可能有两个头试图更新某个表中的同一行,但它们是在单独的事务中进行的。

    我发现的最佳解决方案是设计一些东西,使线程永远不必更新任何其他线程可能更新的行。有时这意味着有一个线程只存在来更新公共表/行。工作线程向该线程发送消息。 (消息可以通过另一个表来完成。)

    我们在产生交易(而不是每天数百万)的许多系统中运行 FB,我们发现一旦设计正确,FB 就会坚如磐石。

    【讨论】:

    • 我认为这是迄今为止最准确的答案——我们已经使用 Firebird 有一段时间了,似乎对存储过程中细节的关注最终会减少或消除这个问题。我还建议使用 IBExpert 进行监控——他们的单个开发人员席位的许可证价格低廉,而且他们的功能集令人印象深刻。
    【解决方案2】:

    在 Firebird 2.1 中,有针对表、连接和事务的新监控功能,也许可以帮助您(如果您可以升级的话)。请参阅 README.monitoring_tables.txt。

    示例,获取活动语句:

    SELECT ATT.MON$USER, ATT.MON$REMOTE_ADDRESS, STMT.MON$SQL_TEXT, STMT.MON$TIMESTAMP
    FROM MON$ATTACHMENTS ATT 
    JOIN MON$STATEMENTS STMT ON ATT.MON$ATTACHMENT_ID = STMT.MON$ATTACHMENT_ID
    WHERE ATT.MON$ATTACHMENT_ID <> CURRENT_CONNECTION AND STMT.MON$STATE = 1
    

    【讨论】:

      【解决方案3】:

      我的建议是编写一个 3 层应用程序,将对数据库的所有访问(插入)序列化到单个线程(其他线程只会在队列中堆积数据)并使用 Firebird 嵌入式(这要快得多,因为它消除了 TCP/IP 开销)。

      除了避免死锁之外,这种方法还可以让您监控队列并查看系统如何应对负载。

      【讨论】:

      • 我投了反对票,因为我不认为瓶颈数据库访问单个线程是这个特定问题的正确答案。您使用 Firebird 的服务器模型而不是嵌入式库的主要原因是支持多个并发客户端。他们已经依赖于服务的这个特性。我们最近转移到它(远离嵌入式),以便用户界面和服务都可以直接访问数据,减少组件之间来回的序列化开销,这只是一个用例示例。
      • 您拥有的并发客户端越多,死锁的可能性就越大。当您有多个可以同时执行的独立操作时,我同意您的评论,但在这种情况下,问题是如何处理相互死锁的并发操作。
      猜你喜欢
      • 2013-09-28
      • 1970-01-01
      • 1970-01-01
      • 2011-12-21
      • 2013-09-08
      • 2010-09-10
      • 2018-06-16
      • 2016-04-08
      相关资源
      最近更新 更多