Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature : skip list for undo data validation #4585

Open
wants to merge 16 commits into
base: 2.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changes/en-us/develop.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Add changes here for all PR submitted to the develop branch.
- [[#5243](https://github.com/seata/seata/pull/5243)] optimize kryo 5.4.0 optimize compatibility with jdk17
- [[#5153](https://github.com/seata/seata/pull/5153)] Only AT mode try to get channel with other app
- [[#5177](https://github.com/seata/seata/pull/5177)] If `server.session.enable-branch-async-remove` is true, delete the branch asynchronously and unlock it synchronously.
- [[#5273](https://github.com/seata/seata/pull/5273)] Optimize the compilation configuration of the `protobuf-maven-plugin` plug-in to solve the problem of too long command lines in higher versions.

### security:
- [[#5172](https://github.com/seata/seata/pull/5172)] fix some security vulnerabilities
Expand All @@ -42,6 +43,7 @@ Thanks to these contributors for their code commits. Please report an unintended
- [Bughue](https://github.com/Bughue)
- [pengten](https://github.com/pengten)
- [wangliang181230](https://github.com/wangliang181230)
- [GoodBoyCoder](https://github.com/GoodBoyCoder)


Also, we receive many valuable issues, questions and advices from our community. Thanks for you all.
2 changes: 2 additions & 0 deletions changes/zh-cn/develop.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
- [[#5243](https://github.com/seata/seata/pull/5243)] 升级 kryo 5.4.0 优化对jdk17的兼容性
- [[#5153](https://github.com/seata/seata/pull/5153)] 只允许AT去尝试跨RM获取channel
- [[#5177](https://github.com/seata/seata/pull/5177)] 如果 `server.session.enable-branch-async-remove` 为真,异步删除分支,同步解锁。
- [[#5273](https://github.com/seata/seata/pull/5273)] 优化`protobuf-maven-plugin`插件的编译配置,解决高版本的命令行过长问题

### security:
- [[#5172](https://github.com/seata/seata/pull/5172)] 修复一些安全漏洞的版本
Expand All @@ -42,6 +43,7 @@
- [Bughue](https://github.com/Bughue)
- [pengten](https://github.com/pengten)
- [wangliang181230](https://github.com/wangliang181230)
- [GoodBoyCoder](https://github.com/GoodBoyCoder)


同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。
5 changes: 5 additions & 0 deletions common/src/main/java/io/seata/common/ConfigurationKeys.java
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,11 @@ public interface ConfigurationKeys {
*/
String TRANSACTION_UNDO_DATA_VALIDATION = CLIENT_UNDO_PREFIX + "dataValidation";

/**
* The constant TRANSACTION_UNDO_DATA_VALIDATION_SKIP.
*/
String TRANSACTION_UNDO_DATA_VALIDATION_SKIP = TRANSACTION_UNDO_DATA_VALIDATION + ".skip";

/**
* The constant TRANSACTION_UNDO_LOG_SERIALIZATION.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@
import java.sql.Timestamp;
import java.sql.Types;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.HashMap;
import java.util.Comparator;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -139,11 +140,24 @@ private static void convertType(Field f0, Field f1) {
* @return the result
*/
public static Result<Boolean> isRecordsEquals(TableRecords beforeImage, TableRecords afterImage) {
return isRecordsEquals(new ArrayList<>(), beforeImage, afterImage);
}

/**
* Is records equals result.
*
* @param beforeImage the before image
* @param afterImage the after image
* @return the result
*/
public static Result<Boolean> isRecordsEquals(List<String> skipLowerList, TableRecords beforeImage,TableRecords afterImage) {
if (beforeImage == null) {
return Result.build(afterImage == null, null);
return Result.build(afterImage == null || skip(skipLowerList, afterImage), null);
} else if (afterImage == null) {
return Result.build(skip(skipLowerList, beforeImage), null);
} else {
if (afterImage == null) {
return Result.build(false, null);
if (skip(skipLowerList, beforeImage) || skip(skipLowerList, afterImage)) {
return Result.ok();
}
if (beforeImage.getTableName().equalsIgnoreCase(afterImage.getTableName())
&& CollectionUtils.isSizeEquals(beforeImage.getRows(), afterImage.getRows())) {
Expand All @@ -158,6 +172,14 @@ public static Result<Boolean> isRecordsEquals(TableRecords beforeImage, TableRec
}
}

private static boolean skip(List<String> skipList, TableRecords image) {
if (CollectionUtils.isEmpty(skipList)) {
return false;
} else {
return skipList.contains(image.getTableName().toLowerCase());
}
}

/**
* Is rows equals result.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import io.seata.common.util.BlobUtils;
import io.seata.common.util.IOUtil;
import io.seata.common.util.StringUtils;
Expand Down Expand Up @@ -77,6 +78,12 @@ public abstract class AbstractUndoExecutor {
public static final boolean IS_UNDO_DATA_VALIDATION_ENABLE = ConfigurationFactory.getInstance()
.getBoolean(ConfigurationKeys.TRANSACTION_UNDO_DATA_VALIDATION, DEFAULT_TRANSACTION_UNDO_DATA_VALIDATION);

/**
* skip list of undo data validation
*/
public static final String UNDO_DATA_VALIDATION_SKIP = ConfigurationFactory.getInstance()
.getConfig(ConfigurationKeys.TRANSACTION_UNDO_DATA_VALIDATION_SKIP, "");

/**
* The Sql undo log.
*/
Expand Down Expand Up @@ -233,10 +240,14 @@ protected boolean dataValidationAndGoOn(ConnectionProxy conn) throws SQLExceptio

TableRecords beforeRecords = sqlUndoLog.getBeforeImage();
TableRecords afterRecords = sqlUndoLog.getAfterImage();
List<String> skipTables = new ArrayList<>();
if (StringUtils.isNotBlank(UNDO_DATA_VALIDATION_SKIP)) {
skipTables = Lists.newArrayList(UNDO_DATA_VALIDATION_SKIP.trim().toLowerCase().split(","));
}

// Compare current data with before data
// No need undo if the before data snapshot is equivalent to the after data snapshot.
Result<Boolean> beforeEqualsAfterResult = DataCompareUtils.isRecordsEquals(beforeRecords, afterRecords);
Result<Boolean> beforeEqualsAfterResult = DataCompareUtils.isRecordsEquals(skipTables, beforeRecords, afterRecords);
if (beforeEqualsAfterResult.getResult()) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Stop rollback because there is no data change " +
Expand All @@ -249,12 +260,12 @@ protected boolean dataValidationAndGoOn(ConnectionProxy conn) throws SQLExceptio
// Validate if data is dirty.
TableRecords currentRecords = queryCurrentRecords(conn);
// compare with current data and after image.
Result<Boolean> afterEqualsCurrentResult = DataCompareUtils.isRecordsEquals(afterRecords, currentRecords);
Result<Boolean> afterEqualsCurrentResult = DataCompareUtils.isRecordsEquals(skipTables, afterRecords, currentRecords);
if (!afterEqualsCurrentResult.getResult()) {

// If current data is not equivalent to the after data, then compare the current data with the before
// data, too. No need continue to undo if current data is equivalent to the before data snapshot
Result<Boolean> beforeEqualsCurrentResult = DataCompareUtils.isRecordsEquals(beforeRecords, currentRecords);
Result<Boolean> beforeEqualsCurrentResult = DataCompareUtils.isRecordsEquals(skipTables, beforeRecords, currentRecords);
if (beforeEqualsCurrentResult.getResult()) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Stop rollback because there is no data change " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.seata.rm.datasource;

import com.google.common.collect.Lists;
import io.seata.rm.datasource.sql.struct.Field;
import io.seata.rm.datasource.sql.struct.Row;
import io.seata.rm.datasource.sql.struct.TableMeta;
Expand Down Expand Up @@ -61,13 +62,16 @@ public void isFieldEquals() {

@Test
public void isRecordsEquals() {
List<String> skipList1 = Lists.newArrayList("Table_name".trim().toLowerCase().split(","));
List<String> skipList2 = Lists.newArrayList("Table_name1".trim().toLowerCase().split(","));
List<String> skipList3 = Lists.newArrayList("Table_name,table_name1".trim().toLowerCase().split(","));
TableMeta tableMeta = Mockito.mock(TableMeta.class);
Mockito.when(tableMeta.getPrimaryKeyOnlyName()).thenReturn(Arrays.asList(new String[]{"pk"}));
Mockito.when(tableMeta.getTableName()).thenReturn("table_name");

TableRecords beforeImage = new TableRecords();
beforeImage.setTableName("table_name");
beforeImage.setTableMeta(tableMeta);
beforeImage.setTableName("table_name");

List<Row> rows = new ArrayList<>();
Row row = new Row();
Expand All @@ -78,15 +82,19 @@ public void isRecordsEquals() {

Assertions.assertFalse(DataCompareUtils.isRecordsEquals(beforeImage, null).getResult());
Assertions.assertFalse(DataCompareUtils.isRecordsEquals(null, beforeImage).getResult());
Assertions.assertTrue(DataCompareUtils.isRecordsEquals(skipList1, beforeImage, null).getResult());
Assertions.assertTrue(DataCompareUtils.isRecordsEquals(skipList1, null, beforeImage).getResult());

TableRecords afterImage = new TableRecords();
afterImage.setTableName("table_name1"); // wrong table name
afterImage.setTableMeta(tableMeta);
afterImage.setTableName("table_name1"); // wrong table name

Assertions.assertFalse(DataCompareUtils.isRecordsEquals(beforeImage, afterImage).getResult());
Assertions.assertTrue(DataCompareUtils.isRecordsEquals(skipList3, beforeImage, afterImage).getResult());
afterImage.setTableName("table_name");

Assertions.assertFalse(DataCompareUtils.isRecordsEquals(beforeImage, afterImage).getResult());
Assertions.assertTrue(DataCompareUtils.isRecordsEquals(skipList3, beforeImage, afterImage).getResult());

List<Row> rows2 = new ArrayList<>();
Row row2 = new Row();
Expand All @@ -95,19 +103,23 @@ public void isRecordsEquals() {
rows2.add(row2);
afterImage.setRows(rows2);
Assertions.assertTrue(DataCompareUtils.isRecordsEquals(beforeImage, afterImage).getResult());
Assertions.assertTrue(DataCompareUtils.isRecordsEquals(skipList3, beforeImage, afterImage).getResult());

field11.setValue("23456");
Assertions.assertFalse(DataCompareUtils.isRecordsEquals(beforeImage, afterImage).getResult());
field11.setValue("12345");
Assertions.assertTrue(DataCompareUtils.isRecordsEquals(skipList3, beforeImage, afterImage).getResult());

field11.setValue("12345");
field12.setName("sex");
Assertions.assertFalse(DataCompareUtils.isRecordsEquals(beforeImage, afterImage).getResult());
field12.setName("age");
Assertions.assertTrue(DataCompareUtils.isRecordsEquals(skipList1,beforeImage, afterImage).getResult());

field12.setName("age");
field12.setValue("19");
Assertions.assertFalse(DataCompareUtils.isRecordsEquals(beforeImage, afterImage).getResult());
field12.setName("18");
Assertions.assertFalse(DataCompareUtils.isRecordsEquals(skipList2, beforeImage, afterImage).getResult());

field12.setName("18");
Field field3 = new Field("pk", 1, "12346");
Row row3 = new Row();
row3.add(field3);
Expand Down