This commit is contained in:
agapple
2019-01-07 13:28:48 +08:00
parent c66b6a0f0f
commit fdf150bd24
4 changed files with 71 additions and 67 deletions

View File

@@ -12,6 +12,7 @@ import java.util.concurrent.Future;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -130,12 +131,17 @@ public class RdbAdapter implements OuterAdapter {
String threads = properties.get("threads"); String threads = properties.get("threads");
// String commitSize = properties.get("commitSize"); // String commitSize = properties.get("commitSize");
rdbSyncService = new RdbSyncService(dataSource, threads != null ? Integer.valueOf(threads) : null); boolean skipDupException = BooleanUtils.toBoolean(configuration.getProperties()
.getOrDefault("skipDupException", "true"));
rdbSyncService = new RdbSyncService(dataSource,
threads != null ? Integer.valueOf(threads) : null,
skipDupException);
rdbMirrorDbSyncService = new RdbMirrorDbSyncService(mirrorDbConfigCache, rdbMirrorDbSyncService = new RdbMirrorDbSyncService(mirrorDbConfigCache,
dataSource, dataSource,
threads != null ? Integer.valueOf(threads) : null, threads != null ? Integer.valueOf(threads) : null,
rdbSyncService.getColumnsTypeCache()); rdbSyncService.getColumnsTypeCache(),
skipDupException);
rdbConfigMonitor = new RdbConfigMonitor(); rdbConfigMonitor = new RdbConfigMonitor();
rdbConfigMonitor.init(configuration.getKey(), this); rdbConfigMonitor.init(configuration.getKey(), this);

View File

@@ -35,10 +35,11 @@ public class RdbMirrorDbSyncService {
private RdbSyncService rdbSyncService; // rdbSyncService代理 private RdbSyncService rdbSyncService; // rdbSyncService代理
public RdbMirrorDbSyncService(Map<String, MirrorDbConfig> mirrorDbConfigCache, DataSource dataSource, public RdbMirrorDbSyncService(Map<String, MirrorDbConfig> mirrorDbConfigCache, DataSource dataSource,
Integer threads, Map<String, Map<String, Integer>> columnsTypeCache){ Integer threads, Map<String, Map<String, Integer>> columnsTypeCache,
boolean skipDupException){
this.mirrorDbConfigCache = mirrorDbConfigCache; this.mirrorDbConfigCache = mirrorDbConfigCache;
this.dataSource = dataSource; this.dataSource = dataSource;
this.rdbSyncService = new RdbSyncService(dataSource, threads, columnsTypeCache); this.rdbSyncService = new RdbSyncService(dataSource, threads, columnsTypeCache, skipDupException);
} }
/** /**

View File

@@ -44,6 +44,7 @@ public class RdbSyncService {
private Map<String, Map<String, Integer>> columnsTypeCache; private Map<String, Map<String, Integer>> columnsTypeCache;
private int threads = 3; private int threads = 3;
private boolean skipDupException;
private List<SyncItem>[] dmlsPartition; private List<SyncItem>[] dmlsPartition;
private BatchExecutor[] batchExecutors; private BatchExecutor[] batchExecutors;
@@ -58,13 +59,15 @@ public class RdbSyncService {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public RdbSyncService(DataSource dataSource, Integer threads){ public RdbSyncService(DataSource dataSource, Integer threads, boolean skipDupException){
this(dataSource, threads, new ConcurrentHashMap<>()); this(dataSource, threads, new ConcurrentHashMap<>(), skipDupException);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public RdbSyncService(DataSource dataSource, Integer threads, Map<String, Map<String, Integer>> columnsTypeCache){ public RdbSyncService(DataSource dataSource, Integer threads, Map<String, Map<String, Integer>> columnsTypeCache,
boolean skipDupException){
this.columnsTypeCache = columnsTypeCache; this.columnsTypeCache = columnsTypeCache;
this.skipDupException = skipDupException;
try { try {
if (threads != null) { if (threads != null) {
this.threads = threads; this.threads = threads;
@@ -182,6 +185,7 @@ public class RdbSyncService {
*/ */
public void sync(BatchExecutor batchExecutor, MappingConfig config, SingleDml dml) { public void sync(BatchExecutor batchExecutor, MappingConfig config, SingleDml dml) {
if (config != null) { if (config != null) {
try {
String type = dml.getType(); String type = dml.getType();
if (type != null && type.equalsIgnoreCase("INSERT")) { if (type != null && type.equalsIgnoreCase("INSERT")) {
insert(batchExecutor, config, dml); insert(batchExecutor, config, dml);
@@ -193,6 +197,9 @@ public class RdbSyncService {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("DML: {}", JSON.toJSONString(dml, SerializerFeature.WriteMapNullValue)); logger.debug("DML: {}", JSON.toJSONString(dml, SerializerFeature.WriteMapNullValue));
} }
} catch (SQLException e) {
throw new RuntimeException(e);
}
} }
} }
@@ -202,7 +209,7 @@ public class RdbSyncService {
* @param config 配置项 * @param config 配置项
* @param dml DML数据 * @param dml DML数据
*/ */
private void insert(BatchExecutor batchExecutor, MappingConfig config, SingleDml dml) { private void insert(BatchExecutor batchExecutor, MappingConfig config, SingleDml dml) throws SQLException {
Map<String, Object> data = dml.getData(); Map<String, Object> data = dml.getData();
if (data == null || data.isEmpty()) { if (data == null || data.isEmpty()) {
return; return;
@@ -240,11 +247,20 @@ public class RdbSyncService {
throw new RuntimeException("Target column: " + targetColumnName + " not matched"); throw new RuntimeException("Target column: " + targetColumnName + " not matched");
} }
Object value = data.get(srcColumnName); Object value = data.get(srcColumnName);
BatchExecutor.setValue(values, type, value); BatchExecutor.setValue(values, type, value);
} }
try {
batchExecutor.execute(insertSql.toString(), values); batchExecutor.execute(insertSql.toString(), values);
} catch (SQLException e) {
if (skipDupException
&& (e.getMessage().contains("Duplicate entry") || e.getMessage().startsWith("ORA-00001: 违反唯一约束条件"))) {
// ignore
// TODO 增加更多关系数据库的主键冲突的错误码
} else {
throw e;
}
}
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Insert into target table, sql: {}", insertSql); logger.trace("Insert into target table, sql: {}", insertSql);
} }
@@ -257,7 +273,7 @@ public class RdbSyncService {
* @param config 配置项 * @param config 配置项
* @param dml DML数据 * @param dml DML数据
*/ */
private void update(BatchExecutor batchExecutor, MappingConfig config, SingleDml dml) { private void update(BatchExecutor batchExecutor, MappingConfig config, SingleDml dml) throws SQLException {
Map<String, Object> data = dml.getData(); Map<String, Object> data = dml.getData();
if (data == null || data.isEmpty()) { if (data == null || data.isEmpty()) {
return; return;
@@ -301,9 +317,7 @@ public class RdbSyncService {
// 拼接主键 // 拼接主键
appendCondition(dbMapping, updateSql, ctype, values, data, old); appendCondition(dbMapping, updateSql, ctype, values, data, old);
batchExecutor.execute(updateSql.toString(), values); batchExecutor.execute(updateSql.toString(), values);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Update target table, sql: {}", updateSql); logger.trace("Update target table, sql: {}", updateSql);
} }
@@ -315,7 +329,7 @@ public class RdbSyncService {
* @param config * @param config
* @param dml * @param dml
*/ */
private void delete(BatchExecutor batchExecutor, MappingConfig config, SingleDml dml) { private void delete(BatchExecutor batchExecutor, MappingConfig config, SingleDml dml) throws SQLException {
Map<String, Object> data = dml.getData(); Map<String, Object> data = dml.getData();
if (data == null || data.isEmpty()) { if (data == null || data.isEmpty()) {
return; return;
@@ -331,9 +345,7 @@ public class RdbSyncService {
List<Map<String, ?>> values = new ArrayList<>(); List<Map<String, ?>> values = new ArrayList<>();
// 拼接主键 // 拼接主键
appendCondition(dbMapping, sql, ctype, values, data); appendCondition(dbMapping, sql, ctype, values, data);
batchExecutor.execute(sql.toString(), values); batchExecutor.execute(sql.toString(), values);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Delete from target table, sql: {}", sql); logger.trace("Delete from target table, sql: {}", sql);
} }

View File

@@ -19,15 +19,10 @@ public class BatchExecutor implements Closeable {
private Connection conn; private Connection conn;
private AtomicInteger idx = new AtomicInteger(0); private AtomicInteger idx = new AtomicInteger(0);
public BatchExecutor(Connection conn){ public BatchExecutor(Connection conn) throws SQLException{
this.conn = conn; this.conn = conn;
try {
this.conn.setAutoCommit(false); this.conn.setAutoCommit(false);
} catch (SQLException e) {
logger.error(e.getMessage(), e);
} }
}
public Connection getConn() { public Connection getConn() {
return conn; return conn;
@@ -40,8 +35,8 @@ public class BatchExecutor implements Closeable {
values.add(valueItem); values.add(valueItem);
} }
public void execute(String sql, List<Map<String, ?>> values) { public void execute(String sql, List<Map<String, ?>> values) throws SQLException {
try (PreparedStatement pstmt = conn.prepareStatement(sql)) { PreparedStatement pstmt = conn.prepareStatement(sql);
int len = values.size(); int len = values.size();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
int type = (Integer) values.get(i).get("type"); int type = (Integer) values.get(i).get("type");
@@ -51,42 +46,32 @@ public class BatchExecutor implements Closeable {
pstmt.execute(); pstmt.execute();
idx.incrementAndGet(); idx.incrementAndGet();
} catch (SQLException e) {
logger.error(e.getMessage(), e);
}
} }
public void commit() { public void commit() throws SQLException {
try {
conn.commit(); conn.commit();
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Batch executor commit " + idx.get() + " rows"); logger.trace("Batch executor commit " + idx.get() + " rows");
} }
idx.set(0); idx.set(0);
} catch (SQLException e) {
logger.error(e.getMessage(), e);
}
} }
public void rollback() { public void rollback() throws SQLException {
try {
conn.rollback(); conn.rollback();
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Batch executor rollback " + idx.get() + " rows"); logger.trace("Batch executor rollback " + idx.get() + " rows");
} }
idx.set(0); idx.set(0);
} catch (SQLException e) {
logger.error(e.getMessage(), e);
}
} }
@Override @Override
public void close() { public void close() {
if (conn != null) { if (conn != null) {
try { try {
if (conn != null) {
conn.close(); conn.close();
} catch (SQLException e) { }
logger.error(e.getMessage(), e); } catch (SQLException ioe) {
} }
} }
} }