我有一系列SQL语句,如下所示:
BEGIN;
SELECT counter FROM table WHERE id=X FOR UPDATE;
REALLY COMPLEX QUERY;
UPDATE table SET counter=Y WHERE id=X;
END;我想在重新计算计数器值时阻止它被读取,但是根据Postgres文档,“行级锁不会影响数据查询;它们只阻止写入器到同一行。”
问题:
发布于 2011-04-12 14:21:18
到1)任何其他会话都将读取由事务修改的数据,就像在“开始”语句之前一样,只要您的事务没有提交。一旦您的事务提交,它将读取计数器的新值。关键是,其他人不必等待,而且总是会看到一致的数据库。
你为什么不试一试“独家访问”呢?(见http://www.postgresql.org/docs/current/static/explicit-locking.html)
编辑:如果不喜欢用“访问独占”锁锁定整个表,也可以使用“咨询锁”(参见上面链接中的13.3.4节)。
发布于 2011-04-16 17:52:46
如果要阻止的读取同时执行同一事务,只需使用不同的数据,请使用UPDATE语句和reads子句。
查看UPDATE语句上的文档。要回答关于独占行锁的点的问题,这是为了防止数据不一致的同时更新。读者在任何时候都能获得数据库的一致视图。
发布于 2011-11-21 21:58:45
在您提供的代码示例中,对该行的所有读取都将看到旧值,直到事务提交为止。
1)假设代码示例以相同的X值同时运行两次。如果实例A已经运行了select ... for update,那么它已经锁定了该行,直到提交为止。执行相同操作的实例B将阻止试图以相同方式获取锁。只有当A提交时,B才能继续。然后,B将得到A在其最后更新中留下的值。
如果Y取决于select ... for update查询读取的值,或者“复杂”部分中的另一个读取值,那么这将产生与连续运行相同的效果--您不会得到其中一个结果将被丢弃的争用条件。
如果Y纯粹是中间复杂查询的结果,那么在没有select ... for update的情况下并行运行它,它们将进行相同的更新。
2) for share将允许该行上的其他选择继续进行,但将导致任何试图阻止select ... for update或update ...的操作,直到完成为止。如果示例代码同时运行两次,它们将在到达update语句时陷入死锁,导致其中一条被中止。
( 3)不。这样做是危险的,因为读者可以阅读一个半更新的字段。(或阅读开始后更新的字段的其余部分。)它还可能破坏一致性,向读者显示在其事务开始后更新的值。
https://dba.stackexchange.com/questions/2154
复制相似问题