问题描述
应用程序A(想想导出器)需要从正在运行的 Postgresql 数据库中读取所有表的所有行。同时应用程序B(想想网络应用程序)继续进行读写。
表 child
有一个可选的 parent
外键。
我遇到了以下访问模式的问题:
-
A:
BEGIN TRANSACTION
-
A:
SELECT * FROM parent
-
B:
BEGIN TRANSACTION
-
B:
INSERT INTO parent
-
B:
INSERT INTO child -- has foreign key to inserted parent
-
B:
COMMIT
-
A:
SELECT * FROM child -- I do not want to receive the inserted child here
应用程序 A 中断,因为它读取了一个 child
,而它无法读取 parent
。因此,我不希望 A 读取 B 插入的 child
行。
据我所知,REPEATABLE_READ
在这里并没有给我任何保证,因为我还没有读过这个事务中的 child
表。据我了解,出于同样的原因,这也不被视为幻读。
-
SERIALIZABLE
是否保证 A 不会读取新的child
行? - 我是否需要借助 A 中的应用逻辑来丢弃对
child
无效引用的parent
行?
解决方法
开始事务 A
START TRANSACTION READ ONLY ISOLATION LEVEL REPEATABLE READ;
那么该事务中的所有语句都会看到数据库的相同状态(快照),无论并发事务修改了什么。
我添加了 READ ONLY
只是因为你说 A 是,它没有必要工作。