diff --git a/changes/en-us/develop.md b/changes/en-us/develop.md index 8e46d61d270..7bc85381c44 100644 --- a/changes/en-us/develop.md +++ b/changes/en-us/develop.md @@ -63,6 +63,7 @@ Add changes here for all PR submitted to the develop branch. - [[#4985](https://github.com/seata/seata/pull/4985)] fix undo_log id repeat - [[#4995](https://github.com/seata/seata/pull/4995)] fix mysql InsertOnDuplicateUpdate duplicate pk condition in after image query sql - [[#5047](https://github.com/seata/seata/pull/5047)] remove useless code +- [[#5051](https://github.com/seata/seata/pull/5051)] undo log dirty throw BranchRollbackFailed_Unretriable ### test: diff --git a/changes/zh-cn/develop.md b/changes/zh-cn/develop.md index add4f462350..72806c6bfc3 100644 --- a/changes/zh-cn/develop.md +++ b/changes/zh-cn/develop.md @@ -63,6 +63,7 @@ - [[#4981](https://github.com/seata/seata/pull/4981)] 优化当tcc栅栏记录查不到时的错误提示 - [[#4995](https://github.com/seata/seata/pull/4995)] 修复mysql InsertOnDuplicateUpdate后置镜像查询SQL中重复的主键查询条件 - [[#5047](https://github.com/seata/seata/pull/5047)] 移除无用代码 +- [[#5051](https://github.com/seata/seata/pull/5051)] 回滚时undolog产生脏写需要抛出不再重试(BranchRollbackFailed_Unretriable)的异常 ### test: - [[#4794](https://github.com/seata/seata/pull/4794)] 重构代码,尝试修复单元测试 `DataSourceProxyTest.getResourceIdTest()` diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java index 656ab7c03b2..ac8026eeb6e 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoExecutor.java @@ -273,7 +273,7 @@ protected boolean dataValidationAndGoOn(Connection conn) throws SQLException { "oldRows:[" + JSON.toJSONString(afterRecords.getRows()) + "]," + "newRows:[" + JSON.toJSONString(currentRecords.getRows()) + "]."); } - throw new SQLException("Has dirty records when undo."); + throw new SQLUndoDirtyException("Has dirty records when undo."); } } return true; diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java index 25c022f247f..95543d3c094 100644 --- a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/AbstractUndoLogManager.java @@ -49,6 +49,7 @@ import static io.seata.common.DefaultValues.DEFAULT_CLIENT_UNDO_COMPRESS_TYPE; import static io.seata.common.DefaultValues.DEFAULT_CLIENT_UNDO_COMPRESS_THRESHOLD; import static io.seata.core.exception.TransactionExceptionCode.BranchRollbackFailed_Retriable; +import static io.seata.core.exception.TransactionExceptionCode.BranchRollbackFailed_Unretriable; /** * @author jsbxyyx @@ -358,9 +359,15 @@ public void undo(DataSourceProxy dataSourceProxy, String xid, long branchId) thr LOGGER.warn("Failed to close JDBC resource while undo ... ", rollbackEx); } } - throw new BranchTransactionException(BranchRollbackFailed_Retriable, String - .format("Branch session rollback failed and try again later xid = %s branchId = %s %s", xid, - branchId, e.getMessage()), e); + if (e instanceof SQLUndoDirtyException) { + throw new BranchTransactionException(BranchRollbackFailed_Unretriable, String.format( + "Branch session rollback failed because of dirty undo log, please delete the relevant undolog after manually calibrating the data. xid = %s branchId = %s", + xid, branchId), e); + } + throw new BranchTransactionException(BranchRollbackFailed_Retriable, + String.format("Branch session rollback failed and try again later xid = %s branchId = %s %s", xid, + branchId, e.getMessage()), + e); } finally { try { diff --git a/rm-datasource/src/main/java/io/seata/rm/datasource/undo/SQLUndoDirtyException.java b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/SQLUndoDirtyException.java new file mode 100644 index 00000000000..9030b5088b7 --- /dev/null +++ b/rm-datasource/src/main/java/io/seata/rm/datasource/undo/SQLUndoDirtyException.java @@ -0,0 +1,31 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.rm.datasource.undo; + +import java.io.Serializable; +import java.sql.SQLException; + +/** + * @author zouwei + */ +class SQLUndoDirtyException extends SQLException implements Serializable { + + private static final long serialVersionUID = -5168905669539637570L; + + SQLUndoDirtyException(String reason) { + super(reason); + } +}