GridDB多事务执行时报10905 TXN_WAIT_FOR_TRANSACTION_END错误的咨询
解决GridDB 10905 TXN_WAIT_FOR_TRANSACTION_END错误的方案
错误原因分析
10905错误本质是同一容器上的并发事务因锁冲突进入等待状态,结合你的代码来看,核心问题有两个:
- 共享了非线程安全的
GridStore实例:GridDB的GridStore对象不支持多线程并发操作,多个线程共用同一个实例会引发事务管理混乱,加剧锁冲突。 - 事务操作同一行数据:你的示例中所有事务都写入主键为1的行,触发行级锁的排他性,导致后续事务必须等待前一个事务释放锁。
具体解决方法
1. 保证线程独立使用GridStore实例
每个线程必须单独获取GridStore连接,避免多线程共享同一个实例。修改后的代码示例:
import com.toshiba.mwcloud.gs.Container; import com.toshiba.mwcloud.gs.GridStore; import com.toshiba.mwcloud.gs.GridStoreFactory; import com.toshiba.mwcloud.gs.Row; import com.toshiba.mwcloud.gs.GSException; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; public class GridDBTransactionTest { public static void main(String[] args) { try { ExecutorService executorService = Executors.newFixedThreadPool(3); for (int i = 0; i < 3; i++) { final int threadId = i; executorService.submit(() -> { GridStore store = null; try { // 每个线程独立获取GridStore实例 store = GridStoreFactory.getInstance().getGridStore(); Container<Row> container = store.getContainer("SampleContainer"); store.setAutoCommit(false); // 写入不同行,避免同一行锁冲突 container.put(new Row(threadId + 1, "Sample Data " + threadId)); store.commit(); } catch (GSException e) { if (store != null) { try { store.rollback(); } catch (GSException ex) { ex.printStackTrace(); } } e.printStackTrace(); } finally { if (store != null) { try { store.close(); } catch (GSException e) { e.printStackTrace(); } } } }); } executorService.shutdown(); } catch (Exception e) { e.printStackTrace(); } } }
2. 优化事务操作粒度,避免锁冲突
- 避免同一行的并发写:如果业务允许,尽量让不同事务操作不同行数据,利用GridDB的行级锁特性提升并发度。
- 缩小事务范围:尽量缩短事务的执行时间,减少锁持有时长,降低冲突概率。
3. 调整GridDB事务参数
- 设置事务超时时间:通过
GridStore.setTransactionTimeout()设置事务等待超时,避免无限等待:store.setTransactionTimeout(5000); // 超时时间5秒 - 调整事务隔离级别:GridDB支持
READ_COMMITTED和REPEATABLE_READ,如果业务允许,使用READ_COMMITTED可以减少锁持有时间:store.setTransactionIsolation(TransactionIsolation.READ_COMMITTED);
4. 安全管理并发事务的最佳实践
- 避免长事务:长事务会持续占用锁资源,大幅提升冲突概率,尽量将大事务拆分为多个小事务。
- 使用乐观锁(可选):如果业务场景允许,通过版本字段实现乐观锁,避免悲观锁的等待:
- 在容器中添加版本字段(如
int version) - 读取数据时获取版本号,更新时校验版本号是否一致,不一致则重试
- 在容器中添加版本字段(如
总结
- 必须保证每个线程使用独立的
GridStore实例,这是解决线程安全问题的基础。 - 优化事务操作的行范围,减少同一行的并发写操作,是降低锁冲突的核心。
- 通过调整事务超时、隔离级别等参数,进一步优化并发性能。
内容的提问来源于stack exchange,提问作者Samar Mohamed
相关产品推荐
相关产品推荐

