auto-flush机制导致主键冲突的问题

- 背景:批量创建订单流程中,创建子订单时出现子订单ID冲突。

- 下图中,第一个子订单创建完成由于不是独立事务后不会立马提交insert语句。而是在第二个子订单的重复校验(查询订单表)中触发了auto-flush提交了insert语句。但是在此时在提交完订单表的insert语句后,提交订单相关表的insert语句中时由于订单相关表过大,或者数据库压力过大导致超时。但是由于没有事务,所以已经执行过的insert语句不会回滚。

接着,代码catch住了auto-flush抛出的异常,并且又查询了一次订单表,此时由于之前autoFlush失败,session中还是存在脏数据,所以会再次触发autoFlush,最终导致insert主键冲突

### 解决Amoeba与MySQL服务器之间的冲突 当遇到Amoeba与MySQL服务器间的冲突时,通常涉及的是查询路由、负载均衡以及主主复制中的数据一致性问题。针对这些问题,可以采取以下措施来确保系统的稳定性和数据的一致性。 #### 配置Amoeba以优化查询分发 为了防止因不当的读写操作引发的数据不一致或性能瓶颈,在`amoeba.xml`中合理设置读写分离策略至关重要[^4]: ```xml <rule name="write"> <pattern>insert|update|delete</pattern> <loadBalance>first</loadBalance> <dbRef> <ref>masterDB</ref> </dbRef> </rule> <rule name="read"> <pattern>select</pattern> <loadBalance>roundrobin</loadBalance> <dbRef> <ref>slaveDB1</ref> <ref>slaveDB2</ref> </dbRef> </rule> ``` 上述配置使得所有的写操作仅由主节点处理,而读请求则被均匀分配给各个从节点,从而减轻单一节点的压力并提高整体响应速度。 #### 调整MySQL配置避免主键冲突 对于采用自增列作为主键的情况,在多主机环境中可能会发生重复ID的问题。为了避免这种情况的发生,可以在每台MySQL实例上通过修改`my.cnf`文件内的参数实现分区编号机制[^3][^5]: ```ini auto-increment-offset = 1 auto-increment-increment = 2 ``` 此设定意味着第一个数据库产生的自动增量将始终为奇数(假设offset设为1),第二个数据库生成偶数值(如果offset调整成2)。这样即使两个独立运行的服务端也能保证各自生产的记录不会产生相同的主键值。 #### 锁定表结构变更期间的操作 在执行任何可能影响现有数据完整性的更改之前——比如迁移版本或是重构表格设计——应当暂时阻止新的事务提交直到当前批次完成为止。这可以通过全局只读模式或者更细粒度的方式达成目的: ```sql FLUSH TABLES WITH READ LOCK; SHOW MASTER STATUS; UNLOCK TABLES; ``` 这些命令序列会暂停所有更新活动直至显式解锁位置,允许管理员安全地实施必要的维护工作而不必担心并发访问带来的风险。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值