记一次MQ异常、且事务自动提交 导致的生产问题
背景:老项目没有做事务处理
因为以前同事在做消息队列时
没有设置手动提交事务,异常处理不当,且数据库交易流水未加唯一索引,而MQ消费异常会自动重发,导致生产出现重复交易数据
正确的消费者端处理方式:
public class ReciveRepayQueue extends NQueueCustomer { @Override public void doExecute() throws Exception { for (Message message:this.getMessageList()){ // Connection conn = getConnection(); Connection conn = DataSourceOperationUtil.getConnection(); conn.setAutoCommit(false); //设置数据库手动提交事务 try { handleBiz(message,conn); conn.commit(); //业务逻辑正常执行完,才commit } catch (Exception e) {
conn.rollback(); //oracle不用rollback,mysql是否需要回滚? e.printStackTrace(); log. throw new Exception(e); } finally { //释放连接 DataSourceOperationUtil.releaseConnection(conn); if (!conn.isClosed()) { conn.close(); } } } } private void handleBiz(Message message, Connection conn) throws Exception { try { ... }catch (Exception e){ log. throw new Exception(e); //抛出异常 } } }
如果事务自动提交,那么异常前的数据会入库,造成脏数据