gpt4 book ai didi

postgresql - PREPARE TRANSACTION 释放锁?

转载 作者:行者123 更新时间:2023-11-29 12:22:00 25 4
gpt4 key购买 nike

我一定是遗漏了一些关于 PostgreSQL 和使用 PREPARE TRANSACTION 的两阶段提交的东西。

以下 SQL:

BEGIN; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1

给出以下锁:

4092    Private 329373  acc     15/53295    RowExclusiveLock    Oui 2013-06-13 18:15:55+02  UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1    
4092 Private 329369 acc 15/53295 RowExclusiveLock Oui 2013-06-13 18:15:55+02 UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1
4092 Private 328704 acc 15/53295 RowExclusiveLock Oui 2013-06-13 18:15:55+02 UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1
4092 Private 327169 acc 15/53295 RowExclusiveLock Oui 2013-06-13 18:15:55+02 UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1
4092 acc 15/53295 15/53295 ExclusiveLock Oui 2013-06-13 18:15:55+02 UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1
4092 Private 329377 acc 15/53295 RowExclusiveLock Oui 2013-06-13 18:15:55+02 UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1
4092 acc 15/53295 ExclusiveLock Oui 2013-06-13 18:15:55+02 UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1

一旦交易准备就绪:

PREPARE TRANSACTION 'TEST'

锁不见了。

因为在 PREPARE 和 COMMIT 之间发生了小的延迟,另一个查询可能会得到一个旧版本的记录。

是否有配置设置来避免这种行为,还是设计使然?

提前致谢。

编辑:我在 Windows x64 上使用 PostgreSQL 9.2.2(PostgreSQL 9.2.2,由 Visual C++ build 1600 编译,64 位)

EDIT 2:以下是完整的测试用例:

在新 session 中发出以下内容:

BEGIN; SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
UPDATE person.tcities set ctyname='L ABERGEMENT CLEMENCIAT TRANSACT' WHERE ctyid = 1
PREPARE TRANSACTION 'TEST';

然后在另一个新 session 中:

SELECT * FROM person.tcities

您将获得旧版本的记录。

最佳答案

我无法在 PostgreSQL 9.2 上重现所描述的行为:

 CREATE TABLE prep_test AS SELECT generate_series(1,10) AS x;

BEGIN;
UPDATE prep_test SET x = x*10;
PREPARE TRANSACTION 'test';

然后在第二个 session 中:

 UPDATE prep_test SET x = x*20;

如预期的那样阻塞,直到我 COMMIT PREPARED 'test'ROLLBACK PREPARED 'test'

我在测试可序列化隔离时也得到了预期的结果:

A# BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
B# BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
A# INSERT INTO prep_test(x) VALUES (42);
B# INSERT INTO prep_test(x) VALUES (43);
A# SELECT count(x) FROM prep_test;
B# SELECT count(x) FROM prep_test;
A# PREPARE TRANSACTION 'test';
B# COMMIT;

B 因可序列化错误而失败,正如预期的那样。如果 B 也尝试 PREPARE TRANSACTION,也会发生同样的情况。

用测试用例更新问题后:

你的测试用例对我来说看起来很好,即它应该完全按照描述的方式运行并且没有错误地执行。

PREPARE TRANSACTION 不是提交。您仍然可以ROLLBACK PREPARED。所以 PostgreSQL 无法向您显示更改的行,直到您执行最后的 COMMIT PREPARED,否则如果您读取行然后执行 ROLLBACK PREPARED,您将得到脏读异常>.

如果您在运行第二个命令之前没有在第一个 session 中PREPARE TRANSACTION,那么您将从测试案例中得到相同的结果。它与准备好的交易无关。您只是没有看到未提交的事务更改了行,这是完全正常的。

如果两个事务都是SERIALIZABLE 那么它仍然没问题。可串行化要求存在 有效的顺序,在该顺序中,并发事务可以连续发生以产生相同的结果。在这里,很明显:SELECT 先出现,然后是 UPDATE。当 SELECT 发生时,事务仍然彼此同时发生,因为使用 PREPARE TRANSACTION 准备的事务在提交或回滚之前仍处于打开状态.

关于postgresql - PREPARE TRANSACTION 释放锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17092561/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com