Java 读锁的Spring事务管理

Java 读锁的Spring事务管理,java,database,spring,transactions,spring-transactions,Java,Database,Spring,Transactions,Spring Transactions,我正在使用Spring进行事务管理。我正在使用@Transactional在我的应用程序中实现spring事务。我的一个场景是,我的应用程序的两个实例读取特定表的所有记录。读取和处理记录后,这些记录将被删除。但我的问题是,在一个实例完成读取之前,处理和删除其他实例会再次读取这些记录。为了解决这个问题,我计划在事务中使用读锁,以便在第一个事务完成之前,所有记录都被锁定。如何使用Spring声明性注释实现这一点。感谢您的帮助。我使用DB2作为我的数据库。 谢谢。基本上,您希望锁定为更新而读取的行,并

我正在使用Spring进行事务管理。我正在使用@Transactional在我的应用程序中实现spring事务。我的一个场景是,我的应用程序的两个实例读取特定表的所有记录。读取和处理记录后,这些记录将被删除。但我的问题是,在一个实例完成读取之前,处理和删除其他实例会再次读取这些记录。为了解决这个问题,我计划在事务中使用读锁,以便在第一个事务完成之前,所有记录都被锁定。如何使用Spring声明性注释实现这一点。感谢您的帮助。我使用DB2作为我的数据库。
谢谢。

基本上,您希望锁定为更新而读取的行,并在选择时跳过锁定的行。在原始SQL中,这将是

SELECT * FROM FOO FOR UPDATE SKIP LOCKED DATA FETCH FIRST 100 ROWS ONLY;

这样,您就不会弄乱另一个事务正在使用的行,两个事务都可以一次处理100行。隔离级别应该是
readcommitted
(可能是您正在使用的默认值)。

您可以使用某种分发机制,通过该机制,每个实例只读取/处理与其他实例不同的特定记录

例如,
1.在键列上应用mod%2函数
从数据库读取一组记录后:
实例1应处理键为%2=0的记录,并放弃/不处理其他记录 实例2应处理键为%2=1的记录,并放弃/不处理其他记录

通过这种方式,即使两个实例都可以读取相同的记录,但我们确信它们将仅由一个节点处理。

如果要删除行,读取锁定是不够的。您使用什么来访问数据库?存储库?JdbcTemplate?我将在读取和处理它之后删除单个事务中的行。但第二个例子是在那段时间内读取那些记录,这是我不想要的。Serializable isolation对我有帮助吗?不是真的,你需要做
选择更新跳过锁定数据
,以获得良好的吞吐量,并让两者都做一些实际工作。默认(spring tx isolation)默认为“基础数据源”的隔离,配置此选项或尝试(至少)
READ_COMMITTED
…在你选择
SERIALIZABLE
…不要选择SERIALIZABLE,它对你没有任何好处。事务将不断回滚,您将浪费时间重做它们,而不是处理行。嗨,Kayaman,谢谢您给我一个直截了当的回答。但不幸的是,我无法更新需要大量批准的SQL语句。不管怎样,我可以在不改变SQL语句的情况下完成这项工作。如果您不能胜任您的工作,请退出并在您所在的位置找到一个。您可以更改事务属性,但不能触摸SQL?这有什么意义呢?您最好只使用应用程序的一个实例,而不要做得太差。我不敢相信,如果不允许您触摸SQL,它们会允许您更改事务属性。我只是在select查询中尝试了“FOR UPDATE SKIP LOCKED DATA FETCH FIRST 100 ROWS ONLY”,似乎两个应用程序都能够读取相同的行。此选择查询未锁定其他实例读取的选定行。然后出现问题<代码>选择…进行更新在事务期间悲观地锁定行(如果不存在事务,则抛出异常)。如果您有权访问可以运行查询的DB2实例,您可以自己测试它。你的隔离度是多少?您确定正在运行正确的查询吗?你的数据库服务器被恶魔控制了吗?他们为什么还要读取其他记录?数据库完全可以只选择id MOD 2为0或1的行。我建议这样做是因为Jewel提到他/她无法更改SQL,需要通过代码来完成某些操作。否则是的,我们肯定可以为此更新SQL。您好,这看起来是个好主意,但适用于两个实例。如果有两个以上的实例试图阅读,我认为这种方法行不通。