Jim*_*ski 6 postgresql postgresql-9.5
在 Postgres 中,如果查询包含在具有可序列化隔离级别的事务中,是否需要使用 FOR UPDATE 锁定表中的行?换句话说,可序列化事务是否会自行锁定行,直到提交事务为止?
好问题。答案是,您不需要使用隔离级别SELECT ... FOR NO KEY UPDATE来避免异常(竞争条件的影响)SERIALIZABLE,但显式锁定行以避免序列化错误仍然很有用。
的设计原则SERIALIZABLE是,您不必担心并发事务会做什么:可以保证,如果您的事务成功,结果将不会受到竞争条件的影响。为了实现这一点,如果数据库无法想到任何其他方法来兑现这一承诺,它可以通过序列化错误中止您的事务。如果发生这种情况,您必须重试该事务,直到成功为止。
举一个具体的例子:如果并发事务在事务读取行和尝试更新行之间修改表行,您将收到序列化错误。如果这种情况经常发生,可能会很烦人,因为这意味着您必须经常重试事务。这对你的整体表现不利。
在这种情况下,显式锁定行以防止并发修改可能会很有用SELECT ... FOR NO KEY UPDATE(是的,如果您打算这样做,那么这是正确的锁定UPDATE;SELECT ... FOR UPDATE仅当您打算使用DELETE唯一约束来锁定行或更新列时才适用)。这种悲观锁会降低并发性,但可以避免序列化错误,因此对于高度竞争的数据来说它是一个不错的选择。