我尝试编写数据库代码以确保它不受争用条件的影响,以确保锁定了正确的行或表。但是我经常想知道:我的代码正确吗?是否可以强迫任何现有的竞赛条件表现出来?我想确保如果它们确实在生产环境中发生,我的应用程序将做正确的事情。

我通常确切地知道哪个并发查询可能会引起问题,但是我不知道如何强制它们同时运行,以查看是否发生了正确的行为(例如,我使用了正确的锁类型),抛出了正确的错误等。

注意:我使用PostgreSQL和Perl,因此,如果不能一概而论,就应该重新标记。

更新:如果解决方案是编程的,我希望这样做。这样,我可以编写自动化测试以确保没有回归。

评论

“种族条件”是指“僵局”吗?

@Gaius ...尽管我确实认为这是某些比赛条件的可能结果

数据库中的@Gaius竞争条件将进行一些操作,例如在创建表之前删除表或在插入表之前更新行。通常,我会想象它是由数据库本身之外的应用程序逻辑处理的。

在插入之前更新行?那不会导致数据库问题。没有竞争条件就像获取一行并对其进行更新,而是让另一个用户在获取该行之后但在处理更新之前对其进行更新。

@MarkD-否。错误地将原子工作单元封装到数据库中会导致多种竞争状况。这是一个例子。请记住,“比赛条件或比赛危险是电子系统或过程中的缺陷,在此过程中,过程的输出或结果出乎意料地严重依赖于其他事件的顺序或时间。” (来源)

#1 楼

我一直在用T-SQL模块来做。

本质上,您需要做的就是从两个或多个连接中循环运行模块几分钟。通常,假设您有一个带有不错CPU的SQL Server盒,那么所有潜在问题都会在几分钟之内暴露出来。

我在这里和这里写了一些例子。

#2 楼

我通常使用RDBMS的命令行工具,只是启动了2个(或更多)CLI实例。然后,您可以一个接一个地重放您的应用程序层正在发送的SQL语句,作为竞赛(看起来像一个动作RPG)。
您应该尝试/感觉锁系统的作用,因为您的CLI会“挂起”,等待锁从其他CLI释放。

如果听起来像泥泞,毫不犹豫地说;-)

评论


您可以举一个逐步的例子吗?可以编写程序测试来做同样的事情吗?

– xenoterracide
2011年1月6日13:20

#3 楼

竞争条件需要多个执行线程,因此要进行单元测试,您将需要能够启动一个或多个线程。在Oracle中,我将使用DBMS_Scheduler运行一个过程来模拟第二个用户。如果PostgreSQL / Perl能够以编程方式启动第二个进程,那么您应该可以执行以下操作:

进程1进程32
很高兴看到关于如何处理比赛条件的思考,更重要的是如何对它们进行单元测试。

评论


我不会将这种测试描述为单元测试,因为单元测试每次都必须以完全相同的方式运行。竞争条件会间歇地使涉及的过程失败,而不是每次都以完全不同的方式失败。

–A-K
2012年3月29日在2:41

@AlexKuznetsov您是正确的,意外的竞争条件会间歇性地显示它们,但是OP指的是他认为代码正在处理的预期条件。这些特定条件可以精确再现,并通过单元测试验证处理方式。

–雷·里菲尔(Leigh Riffel)
2012年3月29日14:19

#4 楼

只要锁定行,就不会遇到通常没有锁定就导致的竞争状态。

但是,如果一个问题阻塞您的问题的时间过长,您可能会陷入僵局。
/>
这很难测试,因为随着数据库的增长查询时间会改变。

对10万行测试数据有效的查询在图表中就没有1000万行。

这种类型的问题可能很难预先发现,但是许多DB都有一些识别慢查询的方法。

通过定期使用这种方法,您应该能够如果有任何警告,则会陷入麻烦。

如果您自己锁定,那是另一回事了,但是我无能为力。

评论


@darioo大声笑我以为wn是某事的首字母缩写…idk他的意思是“自己锁定”。如果他的意思不是使用ORM,则我检查了我的ORM输出的代码,它肯定不会执行锁定权。这就是我希望能够测试潜在比赛条件场景的原因之一。

– xenoterracide
2010-11-29 2:15

是的,我的意思是自己的,通常数据库驱动程序会处理锁定,行,表或可能的字段,但是我只是在开放您使用某些不处理锁定的数据库的可能性;)

– DavidMårtensson
2010-11-29 13:17

..我很确定我是否有一个多语句事务,我的数据库将不知道要自动锁定哪些行...如果选择了行,则不会选择select for update这样的事情...

– xenoterracide
2010-12-5 10:05