我对Postgres还很陌生,我正在尝试弄清楚如何锁定表的特定行。
例如,我有一个用户表:
Name: John, Money: 1
Name: Jack, Money: 2
在后端,我希望选择John,并确保在事务完成之前,没有其他调用可以更新(甚至可能选择)John的行。
我想我需要一个排它锁,从我在网上读到的,我似乎找不到一个很好的例子,锁定一个表的一行在线,你知道吗?
编辑-我应该在方法级别上进行编辑,比如@SqlUpdate(或者其他形式-使用org.skife.jdbi.v2),还是在查询本身中进行编辑?
4条答案
按热度按时间tzcvj98z1#
如果要锁定表中选定的特定行,则需要使用
FOR UPDATE / FOR SHARE
语句对它们执行LOCK FIRST
操作。例如,在您的示例中,如果需要锁定第一行,则执行以下操作:在
SELECT
语句之前的BLOCK1
中,您什么也没做,只是告诉数据库“嘿,我将在此表中执行某些操作,因此当我执行这些操作时,请在此模式下锁定此表”。但是在
BLOCK2
中,当您使用FOR UPDATE
时,您将该行锁定到特定模式的其他事务(阅读doc了解更多详细信息)。将被锁定,直到该事务结束。如果你需要一个例子,做一个测试,并尝试在
BLOCK2
中做另一个SELECT ... FOR UPDATE
,然后再结束第一个事务。它将等待第一个事务结束,并在它之后选择。只有ACCESS EXCLUSIVE锁会阻止SELECT(不带FOR UPDATE/SHARE)语句。
我正在一个函数中使用它来控制子序列,它很棒。希望你喜欢。
6yt4nkrj2#
一旦更新(而不是提交)该行,其他事务就无法更新该行。
如果您想在执行更新之前 * 锁定该行(这似乎没有用),可以使用
select ... for update
来实现。您不能阻止其他会话阅读该行,坦率地说,这也没有意义。
即使你的事务还没有完成(=提交),其他会话也不会看到任何中间(不一致)值--它们看到的是事务开始之前的数据库状态,这就是拥有一个支持事务的关系数据库的全部意义。
bvn4nwqk3#
您可以使用
当您准备好从表中读取时,."SELECT"和所有其他操作将排队,直到事务结束(提交更改或回滚)。
请注意,这将锁定整个表,并且在PostgreSQL中,没有表级锁可以专门锁定特定的行。
所以你可以用
行级别锁定所有将更新行SELECT,这将阻止所有将更新行的SELECT读取您的行!
*FOR UPDATE**导致SELECT语句检索到的行被锁定,就像要进行更新一样。这可以防止在当前事务结束之前,其他事务锁定、修改或删除这些行。即,尝试UPDATE、DELETE、SELECT FOR UPDATE、SELECT FOR NO KEY UPDATE、这些行的SELECT FOR SHARE或SELECT FOR KEY SHARE将被阻塞,直到当前事务结束;相反,SELECT FOR UPDATE将等待在同一行上运行了这些命令中的任何一个的并发事务,然后锁定并返回更新的行(如果行被删除,则不返回任何行)。但是,在REPEATABLE READ或SERIALIZABLE事务中,如果要锁定的行在事务开始后发生了更改,则会抛出错误。有关详细讨论,请参阅13.4节。
FOR UPDATE锁模式也可以由行上的任何DELETE获取,也可以由修改某些列上的值的UPDATE获取。目前,UPDATE情况下考虑的列集是那些具有唯一索引的列,可以在外键中使用(因此不考虑部分索引和表达式索引),但这在将来可能会改变。*
gt0wga4j4#
我正在使用我自己的表,我的表名是paid_properties,它有两列user_id和counter。
由于您希望一次只处理一个事务,因此可以使用以下锁之一:
要测试它,在一个选项卡中运行以下查询(我使用pgadmin4):
并在另一个选项卡中显示以下查询:
您将看到第二个查询在第一个查询完成之前不会执行,您将得到答案94,这在我的情况下是正确的。
如需了解更多信息:https://postgrespro.com/blog/pgsql/5968005https://www.postgresql.org/docs/current/explicit-locking.html
希望这是有帮助的