From e01e48ff658a566c8983a6487834f06c348cda14 Mon Sep 17 00:00:00 2001 From: agapple Date: Sat, 14 Oct 2017 01:14:13 +0800 Subject: [PATCH] fixed h2 support --- deployer/src/main/resources/canal.properties | 3 +- .../resources/example/instance.properties | 6 +- .../main/resources/spring/tsdb/h2-tsdb.xml | 60 +++++++++++++++++++ parse/pom.xml | 4 ++ .../inbound/mysql/tsdb/TableMetaManager.java | 5 +- .../inbound/mysql/tsdb/dao/MetaBaseDAO.java | 59 ++++++++++++++++++ .../mysql/tsdb/dao/MetaHistoryDAO.java | 34 +---------- .../mysql/tsdb/dao/MetaSnapshotDAO.java | 35 +---------- .../main/resources/ddl/h2/meta_history.sql | 21 +++++++ .../main/resources/ddl/h2/meta_snapshot.sql | 17 ++++++ .../parse/inbound/mysql/MysqlDumpTest.java | 2 +- .../mysql/tsdb/TableMetaManagerTest.java | 5 +- parse/src/test/resources/tsdb/h2-tsdb.xml | 44 ++++++++++++++ pom.xml | 5 ++ 14 files changed, 227 insertions(+), 73 deletions(-) create mode 100644 deployer/src/main/resources/spring/tsdb/h2-tsdb.xml create mode 100644 parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/dao/MetaBaseDAO.java create mode 100644 parse/src/main/resources/ddl/h2/meta_history.sql create mode 100644 parse/src/main/resources/ddl/h2/meta_snapshot.sql create mode 100644 parse/src/test/resources/tsdb/h2-tsdb.xml diff --git a/deployer/src/main/resources/canal.properties b/deployer/src/main/resources/canal.properties index 09616194..033a3f89 100644 --- a/deployer/src/main/resources/canal.properties +++ b/deployer/src/main/resources/canal.properties @@ -60,7 +60,8 @@ canal.conf.dir = ../conf canal.auto.scan = true canal.auto.scan.interval = 5 -canal.instance.tsdb.spring.xml=classpath:spring/tsdb/mysql-tsdb.xml +canal.instance.tsdb.spring.xml=classpath:spring/tsdb/h2-tsdb.xml +#canal.instance.tsdb.spring.xml=classpath:spring/tsdb/mysql-tsdb.xml canal.instance.global.mode = spring canal.instance.global.lazy = false diff --git a/deployer/src/main/resources/example/instance.properties b/deployer/src/main/resources/example/instance.properties index 50640d99..bef5cac3 100644 --- a/deployer/src/main/resources/example/instance.properties +++ b/deployer/src/main/resources/example/instance.properties @@ -4,13 +4,15 @@ canal.instance.mysql.slaveId=1234 # position info canal.instance.master.address=127.0.0.1:3306 canal.instance.master.journal.name=mysql-bin.000001 -canal.instance.master.position=68240 +canal.instance.master.position=104606 canal.instance.master.timestamp= # table meta tsdb info canal.instance.tsdb.enable=true -canal.instance.tsdb.url=jdbc:mysql://127.0.0.1:3306/canal_tsdb +canal.instance.tsdb.dir=${canal.file.data.dir:../conf}/${canal.instance.destination:} +canal.instance.tsdb.url=jdbc:h2:${canal.instance.tsdb.dir}/h2;CACHE_SIZE=1000;MODE=MYSQL; +#canal.instance.tsdb.url=jdbc:mysql://127.0.0.1:3306/canal_tsdb canal.instance.tsdb.dbUsername=canal canal.instance.tsdb.dbPassword=canal diff --git a/deployer/src/main/resources/spring/tsdb/h2-tsdb.xml b/deployer/src/main/resources/spring/tsdb/h2-tsdb.xml new file mode 100644 index 00000000..5c3b869d --- /dev/null +++ b/deployer/src/main/resources/spring/tsdb/h2-tsdb.xml @@ -0,0 +1,60 @@ + + + + + + + + + + classpath:canal.properties + classpath:${canal.instance.destination:}/instance.properties + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/parse/pom.xml b/parse/pom.xml index 66e4bb60..0dd84d6f 100644 --- a/parse/pom.xml +++ b/parse/pom.xml @@ -58,6 +58,10 @@ org.apache.ibatis ibatis-sqlmap + + com.h2database + h2 + junit diff --git a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/TableMetaManager.java b/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/TableMetaManager.java index c8fe89e1..4e6a392d 100644 --- a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/TableMetaManager.java +++ b/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/TableMetaManager.java @@ -46,10 +46,11 @@ public class TableMetaManager implements TableMetaTSDB { private static Logger logger = LoggerFactory.getLogger(TableMetaManager.class); private static Pattern pattern = Pattern.compile("Duplicate entry '.*' for key '*'"); + private static Pattern h2Pattern = Pattern.compile("Unique index or primary key violation"); private static final EntryPosition INIT_POSITION = new EntryPosition("0", 0L, -2L, -1L); private String destination; private MemoryTableMeta memoryTableMeta; - private MysqlConnection connection; // 查询meta信息的链接 + private MysqlConnection connection; // 查询meta信息的链接 private CanalEventFilter filter; private CanalEventFilter blackFilter; private EntryPosition lastPosition; @@ -466,7 +467,7 @@ public class TableMetaManager implements TableMetaTSDB { } public boolean isUkDuplicateException(Throwable t) { - if (pattern.matcher(t.getMessage()).find()) { + if (pattern.matcher(t.getMessage()).find() || h2Pattern.matcher(t.getMessage()).find()) { // 违反外键约束时也抛出这种异常,所以这里还要判断包含字符串Duplicate entry return true; } diff --git a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/dao/MetaBaseDAO.java b/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/dao/MetaBaseDAO.java new file mode 100644 index 00000000..968e83b8 --- /dev/null +++ b/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/dao/MetaBaseDAO.java @@ -0,0 +1,59 @@ +package com.alibaba.otter.canal.parse.inbound.mysql.tsdb.dao; + +import java.io.InputStream; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + +import javax.sql.DataSource; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport; + +/** + * @author agapple 2017年10月14日 上午1:05:22 + * @since 1.0.25 + */ +@SuppressWarnings("deprecation") +public class MetaBaseDAO extends SqlMapClientDaoSupport { + + protected boolean isH2 = false; + + protected void initTable(String tableName) throws Exception { + Connection conn = null; + InputStream input = null; + try { + DataSource dataSource = getDataSource(); + conn = dataSource.getConnection(); + String name = "mysql"; + isH2 = isH2(conn); + if (isH2) { + name = "h2"; + } + input = Thread.currentThread() + .getContextClassLoader() + .getResourceAsStream("ddl/" + name + "/" + tableName + ".sql"); + if (input == null) { + return; + } + + String sql = StringUtils.join(IOUtils.readLines(input), "\n"); + Statement stmt = conn.createStatement(); + stmt.execute(sql); + stmt.close(); + } catch (Throwable e) { + logger.warn("init " + tableName + " failed", e); + } finally { + IOUtils.closeQuietly(input); + if (conn != null) { + conn.close(); + } + } + } + + private boolean isH2(Connection conn) throws SQLException { + String product = conn.getMetaData().getDatabaseProductName(); + return StringUtils.containsIgnoreCase(product, "H2"); + } +} diff --git a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/dao/MetaHistoryDAO.java b/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/dao/MetaHistoryDAO.java index e43c5e62..6ec51614 100644 --- a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/dao/MetaHistoryDAO.java +++ b/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/dao/MetaHistoryDAO.java @@ -1,19 +1,10 @@ package com.alibaba.otter.canal.parse.inbound.mysql.tsdb.dao; -import java.io.InputStream; -import java.sql.Connection; -import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.List; -import javax.sql.DataSource; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport; - import com.google.common.collect.Maps; /** @@ -23,7 +14,7 @@ import com.google.common.collect.Maps; * @since 3.2.5 */ @SuppressWarnings("deprecation") -public class MetaHistoryDAO extends SqlMapClientDaoSupport { +public class MetaHistoryDAO extends MetaBaseDAO { public Long insert(MetaHistoryDO metaDO) { return (Long) getSqlMapClientTemplate().insert("meta_history.insert", metaDO); @@ -56,27 +47,6 @@ public class MetaHistoryDAO extends SqlMapClientDaoSupport { } protected void initDao() throws Exception { - Connection conn = null; - InputStream input = null; - try { - DataSource dataSource = getDataSource(); - conn = dataSource.getConnection(); - input = Thread.currentThread().getContextClassLoader().getResourceAsStream("ddl/mysql/meta_history.sql"); - if (input == null) { - return; - } - - String sql = StringUtils.join(IOUtils.readLines(input), "\n"); - Statement stmt = conn.createStatement(); - stmt.execute(sql); - stmt.close(); - } catch (Throwable e) { - logger.warn("init meta_history failed", e); - } finally { - IOUtils.closeQuietly(input); - if (conn != null) { - conn.close(); - } - } + initTable("meta_history"); } } diff --git a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/dao/MetaSnapshotDAO.java b/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/dao/MetaSnapshotDAO.java index 1a3f3053..f525031a 100644 --- a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/dao/MetaSnapshotDAO.java +++ b/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/dao/MetaSnapshotDAO.java @@ -1,18 +1,9 @@ package com.alibaba.otter.canal.parse.inbound.mysql.tsdb.dao; -import java.io.InputStream; -import java.sql.Connection; -import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; -import javax.sql.DataSource; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport; - import com.google.common.collect.Maps; /** @@ -22,7 +13,7 @@ import com.google.common.collect.Maps; * @since 3.2.5 */ @SuppressWarnings("deprecation") -public class MetaSnapshotDAO extends SqlMapClientDaoSupport { +public class MetaSnapshotDAO extends MetaBaseDAO { public Long insert(MetaSnapshotDO snapshotDO) { return (Long) getSqlMapClientTemplate().insert("meta_snapshot.insert", snapshotDO); @@ -59,27 +50,7 @@ public class MetaSnapshotDAO extends SqlMapClientDaoSupport { } protected void initDao() throws Exception { - Connection conn = null; - InputStream input = null; - try { - DataSource dataSource = getDataSource(); - conn = dataSource.getConnection(); - input = Thread.currentThread().getContextClassLoader().getResourceAsStream("ddl/mysql/meta_snapshot.sql"); - if (input == null) { - return; - } - - String sql = StringUtils.join(IOUtils.readLines(input), "\n"); - Statement stmt = conn.createStatement(); - stmt.execute(sql); - stmt.close(); - } catch (Throwable e) { - logger.warn("init meta_history failed", e); - } finally { - IOUtils.closeQuietly(input); - if (conn != null) { - conn.close(); - } - } + initTable("meta_snapshot"); } + } diff --git a/parse/src/main/resources/ddl/h2/meta_history.sql b/parse/src/main/resources/ddl/h2/meta_history.sql new file mode 100644 index 00000000..4c7bbff4 --- /dev/null +++ b/parse/src/main/resources/ddl/h2/meta_history.sql @@ -0,0 +1,21 @@ +CREATE TABLE IF NOT EXISTS `meta_history` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `gmt_create` datetime NOT NULL COMMENT '创建时间', + `gmt_modified` datetime NOT NULL COMMENT '修改时间', + `destination` varchar(128) DEFAULT NULL COMMENT '通道名称', + `binlog_file` varchar(64) DEFAULT NULL COMMENT 'binlog文件名', + `binlog_offest` bigint(20) DEFAULT NULL COMMENT 'binlog偏移量', + `binlog_master_id` varchar(64) DEFAULT NULL COMMENT 'binlog节点id', + `binlog_timestamp` bigint(20) DEFAULT NULL COMMENT 'binlog应用的时间戳', + `use_schema` varchar(1024) DEFAULT NULL COMMENT '执行sql时对应的schema', + `sql_schema` varchar(1024) DEFAULT NULL COMMENT '对应的schema', + `sql_table` varchar(1024) DEFAULT NULL COMMENT '对应的table', + `sql_text` longtext DEFAULT NULL COMMENT '执行的sql', + `sql_type` varchar(256) DEFAULT NULL COMMENT 'sql类型', + `extra` text DEFAULT NULL COMMENT '额外的扩展信息', + PRIMARY KEY (`id`), + UNIQUE KEY meta_history_binlog_file_offest(`destination`,`binlog_master_id`,`binlog_file`,`binlog_offest`), + KEY `meta_history_destination` (`destination`), + KEY `meta_history_destination_timestamp` (`destination`,`binlog_timestamp`), + KEY `meta_history_gmt_modified` (`gmt_modified`) +); \ No newline at end of file diff --git a/parse/src/main/resources/ddl/h2/meta_snapshot.sql b/parse/src/main/resources/ddl/h2/meta_snapshot.sql new file mode 100644 index 00000000..c14d7358 --- /dev/null +++ b/parse/src/main/resources/ddl/h2/meta_snapshot.sql @@ -0,0 +1,17 @@ +CREATE TABLE IF NOT EXISTS `meta_snapshot` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', + `gmt_create` datetime NOT NULL COMMENT '创建时间', + `gmt_modified` datetime NOT NULL COMMENT '修改时间', + `destination` varchar(128) DEFAULT NULL COMMENT '通道名称', + `binlog_file` varchar(64) DEFAULT NULL COMMENT 'binlog文件名', + `binlog_offest` bigint(20) DEFAULT NULL COMMENT 'binlog偏移量', + `binlog_master_id` varchar(64) DEFAULT NULL COMMENT 'binlog节点id', + `binlog_timestamp` bigint(20) DEFAULT NULL COMMENT 'binlog应用的时间戳', + `data` longtext DEFAULT NULL COMMENT '表结构数据', + `extra` text DEFAULT NULL COMMENT '额外的扩展信息', + PRIMARY KEY (`id`), + UNIQUE KEY meta_snapshot_binlog_file_offest(`destination`,`binlog_master_id`,`binlog_file`,`binlog_offest`), + KEY `meta_snapshot_destination` (`destination`), + KEY `meta_snapshot_destination_timestamp` (`destination`,`binlog_timestamp`), + KEY `meta_snapshot_gmt_modified` (`gmt_modified`) +); \ No newline at end of file diff --git a/parse/src/test/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlDumpTest.java b/parse/src/test/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlDumpTest.java index aef55822..a0754635 100644 --- a/parse/src/test/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlDumpTest.java +++ b/parse/src/test/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlDumpTest.java @@ -36,7 +36,7 @@ public class MysqlDumpTest { controller.setMasterPosition(startPosition); controller.setEnableTsdb(true); controller.setDestination("example"); - controller.setTsdbSpringXml("classpath:tsdb/mysql-tsdb.xml"); + controller.setTsdbSpringXml("classpath:tsdb/h2-tsdb.xml"); controller.setEventFilter(new AviaterRegexFilter("test\\..*")); controller.setEventBlackFilter(new AviaterRegexFilter("canal_tsdb\\..*")); controller.setEventSink(new AbstractCanalEventSinkTest>() { diff --git a/parse/src/test/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/TableMetaManagerTest.java b/parse/src/test/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/TableMetaManagerTest.java index b17dd8ea..af8c9dc5 100644 --- a/parse/src/test/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/TableMetaManagerTest.java +++ b/parse/src/test/java/com/alibaba/otter/canal/parse/inbound/mysql/tsdb/TableMetaManagerTest.java @@ -22,7 +22,7 @@ import com.alibaba.otter.canal.protocol.position.EntryPosition; * @since 3.2.5 */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "/tsdb/mysql-tsdb.xml" }) +@ContextConfiguration(locations = { "/tsdb/h2-tsdb.xml" }) public class TableMetaManagerTest { @Resource @@ -40,8 +40,7 @@ public class TableMetaManagerTest { tableMetaManager.apply(position, "tddl5_00", createSql, null); String alterSql = "alter table `test` add column name varchar(32) after c_varchar"; - position = new EntryPosition("mysql-bin.001115", 139177334L, 3065927853L, 1501660815000L); + position = new EntryPosition("mysql-bin.001115", 139177334L, 3065927854L, 1501660815000L); tableMetaManager.apply(position, "tddl5_00", alterSql, null); - } } diff --git a/parse/src/test/resources/tsdb/h2-tsdb.xml b/parse/src/test/resources/tsdb/h2-tsdb.xml new file mode 100644 index 00000000..452e7ee5 --- /dev/null +++ b/parse/src/test/resources/tsdb/h2-tsdb.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index d1471058..649abb36 100644 --- a/pom.xml +++ b/pom.xml @@ -262,6 +262,11 @@ slf4j-api 1.7.12 + + com.h2database + h2 + 1.4.196 + junit