Postgresql 事务如何在读取数据库的上下文中工作?

Postgresql 事务如何在读取数据库的上下文中工作?,postgresql,acid,Postgresql,Acid,我正在使用事务对SQL数据库进行更改。据我所知,这意味着对数据库的更改将以全有或全无的方式进行。我想知道的是,这对阅读有任何保证吗?例如,假设我有如下(伪)代码: 1) start TRANSACTION 2) INSERT INTO users ... // insert some data 3) count = SELECT COUNT(*) FROM ... // count something in the database 4) if count > 10: // do some

我正在使用事务对SQL数据库进行更改。据我所知,这意味着对数据库的更改将以全有或全无的方式进行。我想知道的是,这对阅读有任何保证吗?例如,假设我有如下(伪)代码:

1) start TRANSACTION
2) INSERT INTO users ... // insert some data
3) count = SELECT COUNT(*) FROM ... // count something in the database
4) if count > 10: // do something based on the read
5)     INSERT INTO other_table ... // write based on the read
6) COMMMIT TRANSACTION
在这段代码中,我先执行一个
插入
,然后执行一个
选择
,然后根据
选择
的结果有条件地执行另一个
插入

所以我的问题是,如果另一个进程在步骤(3)和(5)之间修改数据库,那么
count
变量和我的事务会发生什么变化


如果有区别的话,我正在使用PostgreSQL。

我没有在使用PostgreSQL,但我想我可以回答你的问题。认为每个查询都是并行的。我这么说是因为有两个事务:当你插入一个;其他可以插入到b中;然后当你检查b;是否可以看到新数据取决于隔离设置(已提交读取或仅脏读)

还请注意,在数据库中,有一种称为锁定的技术:您可以锁定一个表,以便在提交事务之前防止其他人更改它


希望

正如辛所指出的,这取决于未来

在默认的
readcommitted
级别,来自其他会话的记录在提交时将变得可见;如果根本没有启动事务,您将看到相同的记录(当然,其他进程会在不同的时间看到插入)

使用
REPEATABLE READ
,您的查询将不会在事务开始后看到其他会话提交的任何记录。但是,虽然您不必担心在事务期间更改
SELECT COUNT(*)
的结果,但您不能假设在提交时此结果仍然是准确的

使用
SERIALIZABLE
提供了最有力的保证:如果您的脚本在以独占方式访问数据库时做了正确的事情,那么它将在存在其他可序列化事务时做正确的事情(否则它将彻底失败)。但是,这意味着所有可能干扰您的事务必须使用相同的隔离级别(这是有代价的),并且所有事务都必须准备好在序列化失败时重试其事务

当不能选择可序列化事务时,通常通过显式锁定并发写入来防止竞争条件。锁定选定的记录通常就足够了,但不能准确地锁定
计数(*)
的结果;在你的情况下,你可能需要