可靠地再现数据库争用
我们在数据库表上遇到过一些规律性争用,并且希望评估解决此问题的多种不同选项。
为此,我需要在测试用例中以可重复的可靠性重现表(任何表)上的争用。
我正在考虑的方法是反转锁的语义(例如java.util.concurrent.locks.ReentrantLock)并在开始写入表时释放锁,从而允许所有读取发生在写作开始的时候。
因此,一个写入线程一直持有锁,直到对表进行插入之前不久,然后释放锁,多个读取线程将尝试对同一个表运行 select 语句。
想知道是否对这种方法有任何想法,或者是否有一种更简单的方法可以以 100% 的可靠性重现数据库表上的争用。
谢谢
we experience with some regularity contention on a database table, and would like to evaluate a number of different options for resolving this issue.
in order to do so, i need to reproduce in a test case, contention on a table (any table) with repeatable reliability.
the approach i'm considering would be to reverse the semantics of a lock (e.g. java.util.concurrent.locks.ReentrantLock
) and to release the lock when writing on the table begins, allowing all reads to occur at the time when the writing begins.
So therefore one writer thread holds the lock until shortly before doing an insert to a table, and then releasing the lock, multiple reader threads would attempt to run select statements against the same table.
Was wondering if there were any thoughts on such an approach, or if there is a simpler approach that could, with 100% reliability, reproduce contention on a db table.
thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用计数为
1
的 CountDownLatch。您启动所有读取器线程,其第一个操作是
写入器线程,
此时所有读取器都会愉快地开火。
You could use a CountDownLatch with a count of
1
.You launch all of the reader threads, whose first action is
then the writer thread can
at which point all of the readers will merrily fire away.
在很大程度上取决于您的数据库是否容易产生争用。例如,如果您使用的是 Oracle,那么执行选择将永远不会产生任何争用。
在数据库中产生争用的最简单方法是对您知道需要更新的行进行选择读取。
编辑:重新阅读问题后,我发现您似乎更关心数据库上的“读者”争用而不是更新争用。上述想法可用于强制更新争用,但不能用于强制读者争用。
在这种情况下,您想要启动大量读者来用选择淹没数据库,这不会导致实际争用,只会导致饥饿,那么您可以使用另一个答案中提到的 CountDownLatch ,或者以老式方式进行如果您被迫在 1.5 之前的 JVM 中运行,请使用 Object.wait/Object.notifyAll()。
编辑2:阅读评论后,模拟您所看到的争用的最简单方法可能是使用Sybase 锁定表命令。只需锁定表,启动选择,然后解锁表即可。然后,选择应该全部启动...这也具有最准确地模拟您尝试建模的情况的优点。
It depends a lot on your database as to how easy it is to produce contention in it. For example, if you are using Oracle, then doing a select will never produce any contention.
The easiest way to produce contention in the database is to do a select for read on the row that you know you are about to need to update.
Edit: After re-reading the question, I see that you seem to care more about "reader" contention on the database than update contention. The above idea can be used to force update contention, but not reader contention.
In the case, where you want to launch a mass number of readers to flood the database with selects, which should cause no actual contention, only starvation, then you can use the CountDownLatch as mentioned in another answer, or do it the old fashioned way with Object.wait/Object.notifyAll() if you are forced to run in a pre-1.5 JVM.
Edit 2: After reading the comment, probably the easiest way to emulate the contention that you are seeing is to use the Sybase lock table command. Just lock the table, fire up the selects, and then unlock the table. The selects should then all fire off... this also has the advantage of most accurately emulating the situation that you are trying to model.