我是否需要更高的事务隔离才能使约束在 PostgreSQL 中可靠地工作?
Do I need higher transaction isolation to make constraints work reliably in PostgreSQL?
我有一个情况需要检查某行是否存在,如果存在则不再创建它。大致总结如下:
select id from table where constraintA= and constraintB=
紧接着在我的代码中:
if not exist
insert into table values (,, {other data})
为了确保约束是正确的,我可以制作一个像unique(constraintA,constraintB)
这样的唯一索引。
但是,在 https://www.postgresql.org/docs/10/transaction-iso.html 中它说 Postgres 在行上使用锁,并且新创建的数据与其他并发事务隔离。所以他们不会互相阻止,因为我没有更新或删除数据。
这让我想到了我的问题,我是否需要高于 read committed
的隔离级别来确保正确性?如果不是,我的理解对吗?
PS: 我正在使用 Postgres 10.5
您的担心是对的,但您可以依靠数据库约束按预期工作,即使面对并发事务。
约束在 PostgreSQL 中作为特殊触发器实现,并且触发器函数涉及通过拍摄新快照来“破坏”MVCC,该快照也将看到未提交的行。
这不在常规文档中;对于这样的主题,文档在源代码中。参见 RI_Initial_Check
的 src/backend/utils/adt/ri_triggers.c
, particularly this part。
我有一个情况需要检查某行是否存在,如果存在则不再创建它。大致总结如下:
select id from table where constraintA= and constraintB=
紧接着在我的代码中:
if not exist
insert into table values (,, {other data})
为了确保约束是正确的,我可以制作一个像unique(constraintA,constraintB)
这样的唯一索引。
但是,在 https://www.postgresql.org/docs/10/transaction-iso.html 中它说 Postgres 在行上使用锁,并且新创建的数据与其他并发事务隔离。所以他们不会互相阻止,因为我没有更新或删除数据。
这让我想到了我的问题,我是否需要高于 read committed
的隔离级别来确保正确性?如果不是,我的理解对吗?
PS: 我正在使用 Postgres 10.5
您的担心是对的,但您可以依靠数据库约束按预期工作,即使面对并发事务。
约束在 PostgreSQL 中作为特殊触发器实现,并且触发器函数涉及通过拍摄新快照来“破坏”MVCC,该快照也将看到未提交的行。
这不在常规文档中;对于这样的主题,文档在源代码中。参见 RI_Initial_Check
的 src/backend/utils/adt/ri_triggers.c
, particularly this part。