Java PostgreSql中的事务

Java PostgreSql中的事务,java,postgresql,jdbc,transactions,db2,Java,Postgresql,Jdbc,Transactions,Db2,我想用来自java的PosgreSql实现以下场景: 用户选择数据 用户启动事务:插入、更新、删除数据 用户提交事务 我希望数据在事务处理期间不可供其他用户使用。如果在其他用户尝试更新表时出现异常就足够了 我曾尝试使用选择更新或选择共享,但它也会锁定读取数据。我尝试使用lock命令,但无法获得锁(错误:无法获得关系“fppo10”)的锁,或者另一个事务在尝试提交事务时获得锁,而不是在更新数据时 是否存在一种在事务开始时锁定数据的方法,以防止调用任何其他update、insert或delete

我想用来自java的PosgreSql实现以下场景:

  • 用户选择数据
  • 用户启动事务:插入、更新、删除数据
  • 用户提交事务
我希望数据在事务处理期间不可供其他用户使用。如果在其他用户尝试更新表时出现异常就足够了

我曾尝试使用
选择更新
选择共享
,但它也会锁定读取数据。我尝试使用
lock
命令,但无法获得锁(
错误:无法获得关系“fppo10”
)的锁,或者另一个事务在尝试提交事务时获得锁,而不是在更新数据时

是否存在一种在事务开始时锁定数据的方法,以防止调用任何其他
update
insert
delete
语句


我已经在DB2数据库上成功运行了几年了。现在,我需要同样的应用程序也适用于PostgreSql。

而不是
选择更新
尝试“行独占”表锁:

LOCK TABLE YourTable IN ROW EXCLUSIVE MODE;
根据,此锁:

命令UPDATE、DELETE和INSERT可在上获取此锁定模式 目标表(除任何其他表上的访问共享锁外) 参考表)。一般情况下,该锁定模式将由任何 修改表中数据的命令

请注意,锁的名称令人困惑,但它确实锁定了整个表:

请记住,所有这些锁模式都是表级锁,即使 名称中包含“行”一词;锁定模式的名称如下: 历史的


最后,我想我明白你的意思了。
这本身不是一个“事务”问题(取决于要处理的表的数量和所需的语句,您甚至可能不需要一个),而是一个应用程序设计问题。你有两种方法来处理这个问题;乐观和悲观的锁定

悲观锁定是显式地获取并持有一个锁。当您可以保证将更改行以及与之相关的内容时,以及当您的交易短时,最好使用它。在向帐户添加销售时,一旦进行了购买,您将在更新“当前余额”等情况下使用它(更新将发生,交易持续时间较短,因为此时无需进一步选择)。如果用户读到一行,然后去吃午饭(或度假……),悲观锁定会变得令人沮丧

乐观锁定是读取一行(或一组),而采用任何类型的db层锁定。如果您只是浏览行,而没有立即更新任何行的计划,那么最好使用它。通常,行数据将包括一个“版本”值(递增的计数器或上次更新的时间戳)。如果您的应用程序要更新行,它会比较数据的原始值,以确保它没有首先被其他内容更改,并在数据更改时提醒用户。大多数与用户交互的应用程序都应该使用乐观锁定。但是,它确实要求用户注意并注意更新的值

请注意,由于乐观锁定很少(并且在短时间内)使用锁,因此它通常不会与使用悲观锁的单独进程冲突。悲观锁定应用程序会阻止乐观应用程序更新锁定行,但不会读取它们。
还要注意,这通常不适用于批量更新,因为批量更新几乎没有用户交互(如果有)


tl;博士
不要在读取时锁定行。只需将旧值与应用程序上次读取的值进行比较,如果不匹配,则拒绝更新(并提醒用户)。培训您的用户做出适当的响应。

一方面,您说您希望数据在交易过程中对其他人不可用。另一方面,您不喜欢
select for update
锁定数据以供读取,这在我看来显然是“其他人无法使用”。没有锁会阻止其他客户端尝试执行update语句;有些人会让他们等待。你到底想要什么?@mikesherrill'Cat Recall'问题是,我不知道用户是否想在调用select语句时更新数据。任何更新后都很清楚。但是太晚了,你不知道其他用户想做什么。读一下。@Mike Sherrill的《猫的回忆》我读过了。我在db2上有一个正在工作的应用程序。现在我希望这个应用程序在postgre上也能以同样的方式工作。但这似乎是不可能的:(.取决于您的DB2版本,游标稳定性(也称为Read Committed)如果行已被锁定以进行更新,则将返回单元格的前一个值。也就是说,它的行为就像在updating语句发生之前读取并返回了该行一样,即使事实并非如此。因此,即使您的DB2应用程序也可能没有执行您所期望的操作“将应用程序修复为在并发环境中工作".根据文档,它看起来不错,但是当我尝试它时,在更新表的时候没有抛出异常,但是当调用commit时。虽然这不是我一直在寻找的答案,但我认为这个答案是正确的。我真不敢相信,在Postgre中,在DB2中如此出色地工作而不付出任何努力是不可能的Sql:-(@agad-我有理由相信您的DB2应用程序1]没有真正做到您期望的事情(至少没有完全做到,请参阅我对您的问题的第一条评论),2]没有以用户的最佳利益行事(锁争用的可能性太大)。此外,
SELECT FOR UPDATE
不应用于滚动行-您当前的问题是有两个进程对同一行执行此操作,这当然会发生冲突。但是在滚动过程中先执行
SELECT
而不锁定会将您直接返回到该行