两个进程同时在数据库中保存记录

时间:2012-05-04 10:26:37

标签: ruby database database-design data-storage

当多个用户在数据库(MySQL,Postgres)中同时插入数据时会发生什么?它如何优先考虑首先插入哪个记录以及后面哪个记录。如果答案特定于程序的应用,我要求参考网络应用程序。

2 个答案:

答案 0 :(得分:4)

这绝不是完全相同的时间。一个将在另一个之前发生。 除非你实施自己的优先排序机制,否则哪一个是不确定的,你永远不应该依赖它。

至于将会发生什么,这取决于。

对于同一个表的两个插入,如果数据完整性取决于它们在数据库设计中执行的顺序有一个可怕的缺陷。

对于冲突(例如,对同一记录进行两次更新)。有两种实现方式。

悲观锁定。假设相同数据会有大量更新,因此请锁定它。如果锁定存在,则更新失败(例如,如果第一个尚未完成则为第二个),并带有一些合适的消息。

乐观锁定。假设很少发生碰撞。通常的做法是在记录中添加时间戳字段,以更改每次更新。因此,当您读取数据时,您将获得时间戳,并且当您编写数据时,您只能执行此操作,如果您的时间戳与现在的时间戳匹配,并将所述时间戳更新为其中的一部分。如果不匹配,请执行“其他人更改此数据消息”。

有一个妥协的位置,您尝试合并两个更新。 (例如,您更改名称,我更改地址)。你需要真正考虑这个问题,它很麻烦,而且很快就变得非常复杂,并且错误运行会导致数据混乱。

智商远远超过我的人花了很多时间在这些东西上,我个人喜欢像我一样,简单......

答案 1 :(得分:3)

一般来说,两件事情永远不会在完全的同时发生。有一个工作队列,在某种程度上,一件事总是在另一件事之前发生。

但是,有些情况下整个交易可能需要多个步骤 - 如果这些类型的交易中的两个几乎同时开始,它们可能会在时间上重叠。这可能会导致问题。

例如,想象一个人在购物车中购买东西,步骤包括为他们创建订单记录以及减少和库存计数。如果两个人几乎同时开始这个过程,他们都可能在库存减少之前购买该商品以显示商品缺货。

如果发生类似这样的事情,postgres(和其他现代数据库)提供了限制程序保护自己的方法。这些包括交易锁定

使用交易 (see postgres docs here),语句组作为一个单元运行 - 如果其中一个步骤失败,则所有步骤都“回滚”。 (例如,如果由于项目现在缺货而无法减少库存,则可以回滚订单。)

使用锁定 (see postgres docs here),表格(甚至表格中的各个行)都会被锁定,以便任何其他想要访问它们的进程等待或超时。这将阻止两个进程几乎同时更新相同的数据。

通常,绝大多数应用程序不需要这些方法中的任何一种。除非您在某个环境中工作,例如在涉及的表包含金融交易的银行,您可能不必担心它。