postgresql 关系数据库保证在帐户之间转帐

ffdz8vbo  于 2022-12-12  发布在  PostgreSQL
关注(0)|答案(2)|浏览(128)

假设有一个数据库表:

account
id | balance

只有一种操作可以将资金从一个帐户转移到另一个帐户。如下所示:

START TRANSACTION;
UPDATE account SET balance = balance - 100 WHERE account_id = 1;
UPDATE account SET balance = balance + 100 WHERE account_id = 2;
COMMIT;

从应用程序中,我们可以并行启动从Account1Account2以及从Account2Account1的传输。
我正在尝试理解Isolation level保证。据我所知,在一个事务中不会出现Non-Repeatable问题,因为不会对同一行进行两次读取。因此,我只需要关注Dirty Read场景,Read Commited * 隔离级别 * 为我提供了足够的保证,以确保我的应用程序能够正常工作?
我甚至不需要任何悲观锁来支持这种情况,我的想法对吗?如果不对,你能给予我一个例子,当我的保证被违反时?

06odsfpq

06odsfpq1#

是的,你是对的。默认的READ COMMITTED隔离级别保证没有并发事务可以看到脏数据,并且不会发生异常,因为UPDATE在同一个事务中进行读写。
如果第二笔资金从账户2转移到账户1的时间正好相同,那么可能会发生死锁。但这对数据完整性来说也没有问题。如果所有交易都先用较小的数字更新账户,那么就可以避免这种死锁,而不管转移是从哪个方向进行的。

s6fujrry

s6fujrry2#

在这种情况下,您可以锁定表,直到事务完成

BEGIN
SELECT * FROM account  WHERE  account_id IN(1,2) FOR UPDATE;
UPDATE account SET balance = balance - 100 WHERE account_id = 1;
UPDATE account SET balance = balance + 100 WHERE account_id = 2;
COMMIT;
END ;

还可以锁定整个表,甚至指定一个条件:
在访问独占模式下锁定表帐户;

相关问题