Oracle 12c纯JDBC环境下非规范化表并发写入去重方案咨询
请教:Oracle非规范化表多实例并发更新的重复数据问题
大家好,我遇到了一个Oracle并发更新的棘手问题,想请教下有没有靠谱的解决方案:
背景情况
我手头有个Java项目,用纯JDBC和Oracle 12c做交互,事务隔离级是Read Committed。现在碰到个麻烦:有一张高度非规范化的表,单个实体得拆成多行存储,而且这张表的结构完全没法修改。这张表靠date和hash两列标识实体——注意,这俩只是索引列,既不是主键也不是唯一键。
业务上要求:同一时间同一个实体(不管它包含多少行)只能存在一份,而且实体每天可以被更新多次。目前的更新逻辑是在单个事务里先删再插:
delete from "table" where "date" = ? and "hash" = ? insert into "table" values (?, ?, .....) insert into "table" .... -- 根据实体需求插入多行数据
单实例运行的时候这个逻辑完全没问题,但现在架构是主备两个实例会同时写入相同的数据,这个架构没法调整。要是是规范化表的话,用MERGE语句就能解决,但这张表的结构特殊,MERGE根本用不了。
已尝试的方案及问题
我试过给表加个实例ID列,想用带条件的SELECT来控制INSERT(只有当对应date/hash和实例ID没有数据的时候才插入),结果还是出现了重复数据。后来我想明白了原因:两个事务会先各自执行DELETE,因为Read Committed隔离级看不到对方未提交的删除操作,之后各自执行插入,提交之后就导致重复数据了。
乐观锁我觉得行不通,也不想切换到SERIALIZABLE隔离级——Oracle在这个隔离级下会用乐观并发控制,容易抛出异常,这属于反模式,还会影响性能。现在想问问有没有其他可行的解决方案?
表结构示例
+------+------+---------+ | date | hash | ....... | +------+------+---------+ | date | xyz | ....... | | date | xyz | ....... | | date | xyz | ....... |
内容的提问来源于stack exchange,提问作者Googie
相关产品推荐
相关产品推荐

