使用Firebird对线程中的死锁进行ID识别

时间:2020-03-05 18:53:29  来源:igfitidea点击:

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

发生死锁,它们导致客户端和数据库之间的数据库连接崩溃。

  • 我们将实时数据(每秒一次)发送到数据库。
  • 我们打开了一个大约30个线程的线程池,并使用它们来吸收数据(每秒约1-2 kB)。
  • 有时,数据库只能占用太多资源,以至于我们只能使用池中的下一个线程来使流保持最新状态。

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

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

解决方案

回答

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

我发现最好的解决方案是设计事物,这样线程就不必更新任何其他线程都可能更新的行。有时,这意味着只有一个线程可以更新公共表/行。工作线程将消息发送到此线程。 (该消息可以通过另一个表来完成。)

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

回答

在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层应用程序,将对数据库的所有访问(插入)序列化为一个线程(其他线程只会将数据堆积在队列中),并使用Firebird嵌入式(速度更快,因为它消除了TCP / IP开销)。

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