可靠地再现数据库争用

时间:2009-12-16 17:54:43

标签: java multithreading testing concurrency contention

我们在数据库表上遇到一些规律性争用,并且想要评估解决此问题的许多不同选项。

为了做到这一点,我需要在一个测试用例中重现,在一个表(任何表)上争用可靠性。

我正在考虑的方法是反转锁的语义(例如java.util.concurrent.locks.ReentrantLock)并在开始写表时释放锁定,允许所有读取在写入开始时发生。

因此,一个编写器线程持有锁直到插入表之前不久,然后释放锁,多个读取器线程将尝试对同一个表运行select语句。

想知道是否有任何关于这种方法的想法,或者是否有一种更简单的方法可以100%可靠地重现db表上的争用。

感谢

2 个答案:

答案 0 :(得分:2)

您可以使用CountDownLatch,其计数为1

final CountDownLatch barrier = new CountDownLatch(1);

启动所有读取器线程,其第一个操作是

barrier.await();

那么编写者线程可以

barrier.countDown();

此时所有的读者都会欢快地离开。

答案 1 :(得分:0)

您的数据库在很大程度上取决于在其中产生争用是多么容易。例如,如果您使用的是Oracle,那么执行select将永远不会产生任何争用。

在数据库中产生争用的最简单方法是对您知道需要更新的行执行select选择。

编辑:重新阅读问题之后,我发现您似乎更关心数据库上的“读者”争用而不是更新争用。上述想法可用于强制更新争用,但不能用于读者争用。

在这种情况下,如果你想启动大量的读者来使用选择来充满数据库,这应该不会引起实际争用,只会导致饥饿,那么你可以使用另一个答案中提到的CountDownLatch,或者这样做如果您被迫在1.5之前的JVM中运行,则使用Object.wait / Object.notifyAll()的旧式方法。

编辑2 :阅读评论后,模拟您所看到的争用的最简单方法可能是使用Sybase lock table command。只需锁定表格,启动选择,然后解锁表格。然后选择应该全部启动...这也具有最准确地模拟您试图建模的情况的优势。