处理并发写入和读取

时间:2013-01-10 06:09:35

标签: java concurrency

我正在尝试访问嵌入数据库(H2),其中写入很高(10 /秒,所有都是事件的计数器)。我需要在1分钟左右读取一次数据。读取后,应重置计数器。

我正在尝试实现此行为(伪代码):

//Writer thread
SELECT count FROM counters_db WHERE type="eventID1";
if count:
   count++;
   UPDATE counters_db SET count=count WHERE type="eventID1";
else:
   INSERT INTO counters_db(eventID, count) VALUES(1, "eventID1")

//Reader thread
DATA = SELECT * FROM counters_db;
TRUNCATE TABLE counters_db;
process(DATA) <--Do something with the data

两个线程并行运行。

我看到的问题是:

  1. 编写器线程中的SELECT-UPDATE-INSERT范例看起来很麻烦。如果I TRUNCATE在读者线程中,如果插入了某些内容并且不是读者线程中的select的一部分,我可以丢失数据。

  2. 我确信有更好的方法来处理这些数据,而不是更新计数,然后截断就是将其清除掉。也许只是插入值会起作用(即只是插入的编写器线程中的一个非常简单的逻辑),读者线程将知道要处理哪些行(但是如何?)。这种方法还存在在嵌入式数据库中创建大量记录的风险。我该怎么处理?

  3. 解决此问题的最佳方法是什么?我错过了一些明显的东西?

1 个答案:

答案 0 :(得分:0)

对于#1,(忽略读取器线程),您遇到一个问题,即2个写入器线程同时尝试插入,丢失数据:

  • 使用全局锁定插入计数器。
  • 通常,数据库都有一个updateOrInsert样式命令,可以为您执行此操作。

对于#2,你有一些我能想到的选择:

  • 使用锁(对每个计数器都是细粒度的,或者您的数据库系统允许原子更新)。
  • 准备丢失一些数据。
  • 在阅读方面,您可以记下计数器值是什么(并可能将其写回数据库),从不重置计数器,只需忽略数据&lt;以前的价值。