diff --git a/logs/infra-server.log.2025-05-22.0.gz b/logs/infra-server.log.2025-05-22.0.gz
deleted file mode 100644
index 67228b4..0000000
Binary files a/logs/infra-server.log.2025-05-22.0.gz and /dev/null differ
diff --git a/logs/infra-server.log.2025-05-23.0.gz b/logs/infra-server.log.2025-05-23.0.gz
deleted file mode 100644
index 0064c6c..0000000
Binary files a/logs/infra-server.log.2025-05-23.0.gz and /dev/null differ
diff --git a/tashow-framework/pom.xml b/tashow-framework/pom.xml
index 0e47e10..06d6854 100644
--- a/tashow-framework/pom.xml
+++ b/tashow-framework/pom.xml
@@ -27,6 +27,7 @@
tashow-data-redis
tashow-data-excel
tashow-data-es
+ tashow-data-canal
diff --git a/tashow-framework/tashow-data-canal/pom.xml b/tashow-framework/tashow-data-canal/pom.xml
new file mode 100644
index 0000000..f3daf9d
--- /dev/null
+++ b/tashow-framework/tashow-data-canal/pom.xml
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+
+ com.tashow.cloud
+ tashow-framework
+ ${revision}
+
+ tashow-data-canal
+ jar
+
+ ${project.artifactId}
+ canal 封装拓展
+
+
+
+ com.alibaba.otter
+ canal.client
+ 1.1.0
+
+
+
+
+ com.baomidou
+ dynamic-datasource-spring-boot-starter
+ 4.2.0
+
+
+
+ javax.annotation
+ javax.annotation-api
+ 1.3.2
+
+
+
+ com.tashow.cloud
+ tashow-common
+
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
diff --git a/tashow-framework/tashow-data-canal/src/main/java/com/tashow/cloud/canal/config/CanalAutoConfiguration.java b/tashow-framework/tashow-data-canal/src/main/java/com/tashow/cloud/canal/config/CanalAutoConfiguration.java
new file mode 100644
index 0000000..038eedd
--- /dev/null
+++ b/tashow-framework/tashow-data-canal/src/main/java/com/tashow/cloud/canal/config/CanalAutoConfiguration.java
@@ -0,0 +1,22 @@
+package com.tashow.cloud.canal.config;
+
+import com.tashow.cloud.canal.service.CanalSyncService;
+import com.tashow.cloud.canal.service.SqlExecutorService;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@AutoConfiguration
+public class CanalAutoConfiguration {
+
+ @Bean
+ public CanalSyncService canalSyncService() {
+ return new CanalSyncService();
+ }
+
+ @Bean
+ public SqlExecutorService getdb() {
+ return new SqlExecutorService();
+ }
+}
diff --git a/tashow-framework/tashow-data-canal/src/main/java/com/tashow/cloud/canal/service/CanalSyncService.java b/tashow-framework/tashow-data-canal/src/main/java/com/tashow/cloud/canal/service/CanalSyncService.java
new file mode 100644
index 0000000..64c6a87
--- /dev/null
+++ b/tashow-framework/tashow-data-canal/src/main/java/com/tashow/cloud/canal/service/CanalSyncService.java
@@ -0,0 +1,188 @@
+package com.tashow.cloud.canal.service;
+
+import com.alibaba.otter.canal.client.CanalConnector;
+import com.alibaba.otter.canal.client.CanalConnectors;
+import com.alibaba.otter.canal.protocol.CanalEntry.*;
+import com.alibaba.otter.canal.protocol.Message;
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.BatchPreparedStatementSetter;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.net.InetSocketAddress;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.*;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+@Service
+public class CanalSyncService {
+
+ private static final Logger log = LoggerFactory.getLogger(CanalSyncService.class);
+
+ private static final Queue SQL_QUEUE = new ConcurrentLinkedQueue<>();
+
+ @Autowired
+ private JdbcTemplate jdbcTemplate;
+ @Autowired
+ private SqlExecutorService sqlExecutorService;
+
+ @PostConstruct
+ public void start() {
+ new Thread(this::runCanalClient).start();
+ }
+
+ private void runCanalClient() {
+ CanalConnector connector = CanalConnectors.newSingleConnector(
+ new InetSocketAddress("43.139.42.137", 11111),
+ "example",
+ "",
+ ""
+ );
+ int batchSize = 1000;
+
+ try {
+ connector.connect();
+ connector.subscribe("tashow-platform\\..*");
+ connector.rollback();
+
+ while (true) {
+ Message message = connector.getWithoutAck(batchSize);
+ log.info("Received message id: {}, entries size: {}", message.getId(), message.getEntries().size());
+ long batchId = message.getId();
+ int size = message.getEntries().size();
+
+ if (batchId == -1 || size == 0) {
+ Thread.sleep(1000);
+ continue;
+ }
+
+ dataHandle(message.getEntries());
+ connector.ack(batchId);
+
+ if (!SQL_QUEUE.isEmpty()) {
+ executeQueueSql();
+ }
+ }
+ } catch (Exception e) {
+ log.error("Canal client error occurred.", e);
+ } finally {
+ connector.disconnect();
+ }
+ }
+
+ private void dataHandle(List entries) {
+ for (Entry entry : entries) {
+ if (entry.getEntryType() != EntryType.ROWDATA) continue;
+
+ try {
+ RowChange rowChange = RowChange.parseFrom(entry.getStoreValue());
+ EventType eventType = rowChange.getEventType();
+ String schemaName = entry.getHeader().getSchemaName();
+ String tableName = entry.getHeader().getTableName();
+
+ log.info("schema: {}, table: {}, type: {}", schemaName, tableName, eventType);
+
+ if (eventType == EventType.DELETE) {
+ saveDeleteSql(entry);
+ } else if (eventType == EventType.UPDATE) {
+ saveUpdateSql(entry);
+ } else if (eventType == EventType.INSERT) {
+ saveInsertSql(entry);
+ }
+
+ } catch (Exception e) {
+ log.error("Error handling entry: {}", entry.toString(), e);
+ }
+ }
+ }
+
+ private void saveInsertSql(Entry entry) throws Exception {
+ RowChange rowChange = RowChange.parseFrom(entry.getStoreValue());
+ String tableName = entry.getHeader().getTableName();
+
+ for (RowData rowData : rowChange.getRowDatasList()) {
+ List columns = rowData.getAfterColumnsList();
+
+ List columnNames = new ArrayList<>();
+ List