SQL 如何处理多个进程同时将同一条记录写入同一个数据库 table?

How SQL would handle multiple process writes the same record into the same database table simultaneously?

这是我长期以来的困惑。如果多个进程同时将相同的记录写入同一个数据库table,它们会发生冲突吗?

类似的问题,比如一台master机器不停的向其他很多机器分发请求,比如在机器-A上的table中插入一条记录。不知何故,此操作在机器 A 上非常慢,主控制器将向机器 B 重新发送完全相同的请求。那么会发生什么呢?会有冲突吗?

实际上有两个问题,但我会尽量回答主要问题。

首先,我们在谈论什么样的数据库?如果它是像 Oracle、PostgreSQL、MSSQL 等现代 RDBMS,那么很可能它具有 lock-by-row 机制,这意味着每个进程可以同时 insert/update/delete 行,只要它们不相互交叉。

一旦发生两个进程试图更新同一行,一个进程(幸运的是第一个)将更新该行,而第二个进程将不得不等到第一个进程提交或回滚它的交易。此更新的行现在已被任何进程锁定以进行任何更改,但第一个进程除外。

如果第一个进程删除一行,也会发生同样的事情。在第一个提交或回滚事务之前,没有其他进程可以插入具有相同唯一键的新行。

现在,当我们遇到两个进程使用相同的唯一键插入行时,它变得更有趣了,如果让它们都完成,将破坏关系模型。 table 中还没有行,所以没有要锁定的内容。但是,某处有一个索引可以提供唯一性。因此,进程实际上不会锁定行,而是会尝试锁定索引的存储桶。最初的过程将会成功。现在,当第二个进程尝试插入一行时,它会看到存储桶已锁定。与第一种情况一样,第二个进程必须等到桶被释放,然后检查是否可以插入并为自己锁定桶。

这实际上是一个非常肤浅和笼统的解释,但它给出了冲突解决机制如何工作的概念。实际实现可能因数据库而异,并且要复杂得多。