You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Infinispan 9.4事务beforeCompletion阶段执行put操作失败如何解决?

问题场景

使用Infinispan 9.4,缓存配置如下:

<local-cache name="localCache">
  <locking isolation="READ_COMMITTED"/>
  <transaction mode="BATCH"/>
  <memory>
     <object strategy="NONE"/>
  </memory>
</local-cache>

在事务的beforeCompletion阶段执行缓存写入操作:

tx.registerSynchronization(new Synchronization()
{
    // 省略其他方法实现
    public void beforeCompletion()
    {
      cache.put(CACHE_KEY, value);
    }
}

执行后抛出UnsupportedOperationException,核心异常栈如下:

ERROR impl.InvocationContextInterceptor - ISPN000136: Error executing command PutKeyValueCommand on Cache 'localCache', writing keys [storage] 

java.lang.UnsupportedOperationException: null
    at org.infinispan.commons.util.ImmutableListCopy.add(ImmutableListCopy.java:124) ~[infinispan-commons-9.4.24.Final.jar:9.4.24.Final]
    at org.infinispan.transaction.impl.LocalTransaction.addModification(LocalTransaction.java:66) ~[infinispan-core-9.4.24.Final.jar:9.4.24.Final]
    at org.infinispan.interceptors.impl.TxInterceptor.lambda$handleWriteCommand$8(TxInterceptor.java:414) ~[infinispan-core-9.4.24.Final.jar:9.4.24.Final]
    // 其余栈信息省略

非beforeCompletion阶段执行该写入操作正常,但业务要求必须在该阶段完成此操作,需解决该异常。

解决方案

根因

缓存采用BATCH事务模式时,Infinispan会在事务提交流程早期将事务的修改列表转换为不可变集合(ImmutableListCopy),此时在beforeCompletion阶段尝试添加新修改,会触发不可变集合的add操作不支持异常。

可行解决方式

1. 切换事务模式

将缓存事务模式从BATCH改为NON_XA或LOCAL,这两种模式下事务修改列表在beforeCompletion阶段仍保持可变:

<local-cache name="localCache">
  <locking isolation="READ_COMMITTED"/>
  <transaction mode="NON_XA"/> <!-- 或 LOCAL -->
  <memory>
     <object strategy="NONE"/>
  </memory>
</local-cache>

2. 在beforeCompletion中启动独立事务

若必须保留BATCH模式,可在beforeCompletion中挂起当前事务,启动新事务执行缓存写入,完成后恢复原事务:

public void beforeCompletion()
{
    TransactionManager tm = TransactionManagerLookup.getTransactionManager();
    Transaction suspendedTx = null;
    try {
        suspendedTx = tm.suspend();
        tm.begin();
        cache.put(CACHE_KEY, value);
        tm.commit();
    } catch (Exception e) {
        // 异常处理,如日志记录
        e.printStackTrace();
    } finally {
        if (suspendedTx != null) {
            try {
                tm.resume(suspendedTx);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

注意:新事务的提交结果与原事务独立,需自行处理新事务的异常情况。

3. 预注册修改到原事务

调整业务逻辑,在进入beforeCompletion之前,将需要写入的操作提前加入原事务,避免在提交阶段修改事务状态。

内容的提问来源于stack exchange,提问作者Denis Abramov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 11:15:01