gpt4 book ai didi

spring - 数据库读锁定

转载 作者:行者123 更新时间:2023-12-04 19:31:28 25 4
gpt4 key购买 nike

我有一个用例,我需要在一个事务中执行以下操作:

  1. 开始交易
  2. 向表中插入一个项目
  3. 选择表格中的所有项目
  4. 将选定的项目转储到一个文件中(这个文件是有版本控制的,另一个程序总是使用最新版本)
  5. 如果以上所有事情都成功,则提交事务,否则,回滚。

如果两个事务几乎同时开始,则有可能在第一个事务 A 提交它插入到表中的内容(步骤 4)之前,第二个事务 B 已经执行了 SELECT 操作(步骤 2),其结果还不包含第一个事务插入的项目(因为它还没有被 A 提交,所以不B 可见)。在这种情况下,当 A 完成时,它将正确转储包含其插入项的文件 File1。稍后,B 完成后,它将转储另一个文件 File2,其中仅包含其插入的项目,但不包含 A 插入的项目。由于 File2 更新,我们将使用 File2。问题是 File2 不包含 A 插入的项目,即使该项目在数据库中很好

我想知道当事务向表中插入某些内容直到提交或回滚时,通过锁定表的读取(SELECT) 来解决此问题是否可行,如果可以,如何在 Spring with Oracle as DB 中实现这种锁定。

最佳答案

您需要在事务之间进行某种同步:

  1. 开始交易
  2. 获取锁以防止另一个 session 中的事务继续或等待直到另一个 session 中的事务完成
  3. 向表中插入一个项目
  4. 选择……
  5. ……
  6. 提交并释放锁

最简单的方法是使用 LOCK TABLE命令,至少在 SHARE 模式下(也可以使用 SHARE ROW EXCLUSIVE 或 EXCLUSIVE 模式,但它们对这种情况的限制太大)。
这种方法的优点是锁在提交或回滚时自动释放。
缺点是,这个锁会干扰系统中同时更新此表的其他事务,并可能降低整体性能。


另一种方法是使用 DBMS_LOCK包裹。
此锁不会影响其他未明确使用该锁的事务。
缺点是这个包不好用,commit和rollback都不会释放锁,必须在事务结束时显式释放锁,所以所有的异常都要小心处理,否则会死锁很容易发生。


另一种解决方案是创建一个“虚拟”表,其中只有一行,例如:

CREATE TABLE my_special_lock_table(
int x
);
INSERT INTO my_special_lock_table VALUES(1);
COMMIT:

然后使用SELECT x FROM my_special_lock_table FOR UPDATE
或者 - 甚至更简单 - 在您的交易中简单地 UPDATE my_special_lock_table SET x=x
这将在此表中的一行上放置排他锁,并仅同步此一个事务。
缺点是必须创建另一个“虚拟”表。
但是这个解决方案不会影响系统中的其他事务,锁会在提交或回滚时自动释放,并且它是可移植的——它应该适用于所有其他数据库,而不仅仅是在 Oracle 中。

关于spring - 数据库读锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41944767/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com