检查唯一列的值是否存在或让db在插入时引发唯一错误的利弊


8

前几天写查询时,一个念头浮现在我的脑海。

最好是先检查唯一列的值是否存在,然后插入或插入,然后让db引发唯一约束错误?会不会很重要?

编辑:正如下面的建议,这个问题取决于数据库,我正在添加标签postgresql。

Answers:


3

我不认为您的问题确实与数据库无关。正确的答案可能取决于实施细节,具体细节可能因供应商而异,并且随着下一个版本的变化而变化。在任何RDBMS上选择任何方法之前,我都会在并发下进行测试。

现在,在SQL Server 2008 R2上,我正在使用以下内容:

  1. 低并发性和低修改量。要保存一行,我使用sp_getapplock进行序列化并使用MERGE。我强调在高并发下进行测试以验证其是否有效。

  2. 更高的并发性和/或数量。为了避免并发和提高性能,我不会一次保存一行。我在我的应用服务器上累积更改,并使用TVP保存批次。尽管如此,为避免并发相关问题,我在合并之前使用sp_getapplock进行了序列化。同样,我在高并发性下进行压力测试以验证其是否有效。

结果,我们在生产中具有良好的性能和与零并发相关的问题:无死锁,无PK /唯一约束违规等。


所以您的意思是说,如果并发问题得到很好的处理,那么先检查是个好主意吗?
codecool 2012年

1
是的,通常避免错误要比引发和捕获异常更好,但是您需要在平台上对其进行基准测试。
AK

7

让数据库引发一个错误。

先进行测试对于并发并不安全,因为最终会导致冲突,因为两个线程可能会通过“ NOT EXIST”,并且两个线程都将尝试写入。这适用于“ READ COMMITTED”和MVCC / Snapshot锁定策略。

您可以使用锁定提示来强制隔离,但会降低性能。

我将其称为JFDI模式(SO链接)。对于“如果存在则更新”,请在此处查看:需要帮助Sql Server 2005死锁方案进行故障排除。这些是SQL Server。MySQL具有INSERT IGNORE,可以很好地处理这个问题。不确定其余


好的 我没有想到这一点!在并发的情况下,检查甚至可能失败。:)
codecool 2012年


我认为执行检查(并正常失败)但遵循“信任但验证”的格言来捕获失败是很有用的。原因?错误处理非常昂贵。实际上,我今天正在进行一些测试,这些测试应该可以揭示此注释是否有意义。如果该评论消失,您将知道结果。:-)
亚伦·伯特兰

同样在2008年,有MERGE可能解决了Paul的观察,但是我还没有以高tx率对其进行测试。主要是因为我尚未训练我的大脑来理解该语法。
亚伦·伯特兰

1
Mea culpa。我今天在测试中做了一些观察。请记住,这些是非常孤立的测试,没有并发性。对于平直刀片,首先检查并避免出现错误的速度比让错误发生的速度快10倍。但是在其他情况下,您将执行更复杂的错误处理(TRY / CATCH或IF @@ ERROR <> 0,使用ROLLBACK或THROW等),如果您先进行检查,则速度大约是原来的两倍。再次强调一下,这只是我的初步观察,有很多因素会影响其产生的影响。我可能要过一段时间才能彻底写博客。
亚伦·伯特兰
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.