在一个具有三列(serial id, varchar name, varchar email)并具有两个不同事务并行执行的表中,如下所示:
交易1:
BEGIN;
INSERT INTO public.users (name, email) VALUES ('tart', 'tart@warm.com');
INSERT INTO public.users (name, email) VALUES ('tart123', 'tart123@warm123.com');
COMMIT;Transaction2:
BEGIN;
INSERT INTO public.users (name, email) VALUES ('raspy', 'raspy@sun.com');
INSERT INTO public.users (name, email) VALUES ('raspy123', 'raspy123@sun123.com');
COMMIT;结果是否有可能变成以下情况?
1 | tart | tart@warm.com
2 | raspy | raspy@sun.com
3 | tart123 | tart123@warm123.com
4 | raspy123 | raspy123@sun123.com发布于 2018-11-20 19:11:15
serial在PostgreSQL文档中是这样定义的:
数据类型
smallserial、serial和bigserial不是真类型,而只是创建唯一标识符列(类似于其他数据库支持的AUTO_INCREMENT属性)的一种符号方便。
他们还提出了这一警告:
由于
smallserial、serial和bigserial是使用序列实现的,因此列中出现的值序列可能存在“漏洞”或空白,即使没有删除任何行。从序列中分配的值仍然“用完”,即使包含该值的行从未成功插入表列。例如,如果插入事务回滚,则可能发生这种情况。有关详细信息,请参阅第9.16节中的nextval()。
如果您转到nextval文档,您将得到:
将sequence对象提升到其下一个值并返回该值。这是原子性的:即使多个会话同时执行nextval,每个会话都将安全地接收一个不同的序列值。
序列是一个共享对象,在您的所有内容中。默认情况下,每个对INSERT的调用都将调用底层序列nextval,并将提供一个值,而不管刚才在事务中发生了什么。因此,值将完全取决于操作的顺序,而不是首先启动哪个事务或诸如此类的事情。
您还可以得到这个结果(取决于您的DB中其他地方同时发生了什么):
1 | tart | tart@warm.com
7 | raspy | raspy@sun.com
13 | tart123 | tart123@warm123.com
42 | raspy123 | raspy123@sun123.com或
1 | tart | tart@warm.com
3 | raspy | raspy@sun.com
2 | tart123 | tart123@warm123.com
4 | raspy123 | raspy123@sun123.com(这可能是你所期望的,但没有具体的保证)。
序列只是保证在两个单独的地方“永远”得到相同的值,它并不保证在增量中缺少洞或单调,特别是在多个事务中。
https://dba.stackexchange.com/questions/223000
复制相似问题