Compare commits

..

22 Commits

Author SHA1 Message Date
agapple
8375ea4b7d [maven-release-plugin] prepare release canal-1.0.21 2015-12-30 16:23:20 +08:00
agapple
72ceb58fa3 fixed issue #135 , isUpdate bugfix 2015-12-02 14:37:06 +08:00
agapple
44f2b74862 fixed issue #130 , support mysql5.6 time2/timestamp2/datetime2 javaType 2015-11-13 14:16:12 +08:00
agapple
5a34195201 Merge pull request #128 from likeloveluck/simple_ddl_pattern
fix rename table ddl parser tablename and schemaname error
2015-09-07 15:49:12 +08:00
jiawei
d976932177 fix rename table ddl parser tablename and schemaname error 2015-09-01 12:17:41 +08:00
agapple
d887c8f763 Merge pull request #127 from dozer47528/master
fix not skip filter and read the error data
2015-08-04 11:24:14 +08:00
Dozer
197a1446b7 fix not skip filter and read the error data 2015-07-31 17:18:42 +08:00
agapple
155c00b256 Merge pull request #124 from smilingleo/master
fixed a hard coded mysql host ip address
2015-07-28 13:51:44 +08:00
Leo
b16f4844a1 fixed a hard coded mysql host ip address 2015-07-23 10:42:03 +08:00
agapple
f2f2bfb538 add rename testcase 2015-07-17 14:43:15 +08:00
agapple
5f6580399c fixed format 2015-07-17 14:41:39 +08:00
agapple
10930b9e3d Merge pull request #122 from likeloveluck/rename_bug_fix
修复rename table命令中包含多个表,解析失败问题
2015-07-17 14:33:38 +08:00
jiawei
d1afeb7540 change result reference 2015-07-16 19:25:46 +08:00
jiawei
119af9fca1 change rename operate 2015-07-15 19:20:30 +08:00
agapple
f0ce4b569e Merge pull request #121 from huyanping/patch-1
Update README.md
2015-07-14 16:59:24 +08:00
Jenner
4459b8acdf Update README.md 2015-07-14 14:42:13 +08:00
agapple
bb5d5749bd Merge pull request #120 from smilingleo/master
增加了一个脚本来自动获取mysql master binlog信息,并自动更新instance配置文件
2015-07-05 11:10:56 +08:00
smilingleo
169baafb8b correct format 2015-07-03 10:32:40 +08:00
smilingleo
199f30de87 add a script to fetch mysql master binlog file and sync position automatically 2015-07-03 10:29:58 +08:00
smilingleo
87c14f0b51 Revert "test"
This reverts commit f35d965f63.
2015-07-03 10:08:03 +08:00
smilingleo
f35d965f63 test 2015-07-03 10:02:10 +08:00
agapple
9956b3557f [maven-release-plugin] prepare for next development iteration 2015-06-30 10:23:54 +08:00
25 changed files with 240 additions and 44 deletions

View File

@@ -36,7 +36,7 @@
<li>slave重做中继日志中的事件,将改变反映它自己的数据。</li>
</ol>
<h3>canal的工作原理:</h3>
<p><img width="590" src="http://dl.iteye.com/upload/attachment/0080/3107/c87b67ba-394c-3086-9577-9db05be04c95.jpg" alt="" height="273">
<p><img width="590" src="https://camo.githubusercontent.com/46c626b4cde399db43b2634a7911a04aecf273a0/687474703a2f2f646c2e69746579652e636f6d2f75706c6f61642f6174746163686d656e742f303038302f333130372f63383762363762612d333934632d333038362d393537372d3964623035626530346339352e6a7067" alt="" height="273">
<p>原理相对比较简单:</p>
<ol>
<li>canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议</li>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.alibaba.otter</groupId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>canal.common</artifactId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.alibaba.otter</groupId>

View File

@@ -163,10 +163,13 @@ public final class RowsLogBuffer {
case LogEvent.MYSQL_TYPE_TIMESTAMP:
case LogEvent.MYSQL_TYPE_DATETIME:
case LogEvent.MYSQL_TYPE_TIMESTAMP2:
case LogEvent.MYSQL_TYPE_DATETIME2:
javaType = Types.TIMESTAMP;
break;
case LogEvent.MYSQL_TYPE_TIME:
case LogEvent.MYSQL_TYPE_TIME2:
javaType = Types.TIME;
break;

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.alibaba.otter</groupId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.alibaba.otter</groupId>

View File

@@ -74,6 +74,8 @@ public class FieldPacket extends PacketWithHeaderPacket {
this.decimals = data[index];
index++;
//
index += 2;//skip filter
//
if (index < data.length) {
reader.setIndex(index);
this.definition = reader.readLengthCodedString(data);

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.alibaba.otter</groupId>

90
example/src/main/bin/init.sh Executable file
View File

@@ -0,0 +1,90 @@
#! /bin/bash
current_path=`pwd`
case "`uname`" in
Linux)
bin_abs_path=$(readlink -f $(dirname $0))
;;
*)
bin_abs_path=`cd $(dirname $0); pwd`
;;
esac
base=${bin_abs_path}/..
# default values
PORT=3306
MYSQL_IP="0"
# parse arguments
while getopts "h:p:" opt; do
case $opt in
p)
if [[ $OPTARG -gt 0 ]]; then
PORT=$OPTARG
else
echo "Invalid -p option: -$OPTARG, should be positive integer >&2"
exit 1
fi
;;
h)
MYSQL_IP=$OPTARG
;;
\?)
printUsage
exit 1
;;
esac
done
function printUsage
{
cat << __Usage
Initialise the instance config property file automatically. This tool will connect to Mysql master server and get the binlog file and position then update the instance config property file for you.
Usage: $0 -p [port] -h [hostname]
Options:
-p: mysql port, default to 3306
-h: mysql host ip.
For example:
$0 -p 3306 -h 172.17.0.2
Enjoy!!!
__Usage
}
if [[ $PORT -lt 0 ]]; then
echo "invalid port argument $PORT"
printUsage
exit 1
fi
# check if mysql ip is specified
if [[ $MYSQL_IP = "0" ]]; then
echo '-h mysql host ip argument is required.'
printUsage
exit 1
fi
MYSQL_ADDR="$MYSQL_IP:$PORT"
MASTER_STATUS=`mysql -ucanal -pcanal -h$MYSQL_IP -P$PORT -e 'show master status' 2>/dev/null | head -n 2 | tail -n 1`
LOG_FILE=`echo "$MASTER_STATUS" | cut -f 1`
LOG_POS=`echo "$MASTER_STATUS" | cut -f 2`
INSTANCE_CONF_FILE=$base/conf/example/instance.properties
if [ ! -f $INSTANCE_CONF_FILE ]; then
echo "Can not find instance config file: $INSTANCE_CONF_FILE"
exit 1
fi
# replace the binlog file and position
sed -i.bak -e "s/canal\.instance\.master\.address = .*/canal\.instance\.master\.address = $MYSQL_ADDR/" -e "s/canal\.instance\.master\.journal\.name = .*/canal\.instance\.master\.journal\.name = $LOG_FILE/" -e "s/canal\.instance\.master\.position = .*/canal\.instance\.master\.position = $LOG_POS/" $INSTANCE_CONF_FILE
cat $INSTANCE_CONF_FILE
echo
echo 'Above is your instance config file, check if the settings are correct'
echo

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.alibaba.otter</groupId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<artifactId>canal.instance.core</artifactId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<groupId>com.alibaba.otter</groupId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.alibaba.otter</groupId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<groupId>com.alibaba.otter</groupId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.alibaba.otter</groupId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>canal.parse</artifactId>

View File

@@ -215,12 +215,20 @@ public class LogEventConvert extends AbstractCanalLifeCycle implements BinlogPar
// 更新下table meta cache
if (tableMetaCache != null
&& (result.getType() == EventType.ALTER || result.getType() == EventType.ERASE || result.getType() == EventType.RENAME)) {
if (StringUtils.isNotEmpty(tableName)) {
// 如果解析到了正确的表信息,则根据全名进行清除
tableMetaCache.clearTableMeta(schemaName, tableName);
} else {
// 如果无法解析正确的表信息,则根据schema进行清除
tableMetaCache.clearTableMetaWithSchemaName(schemaName);
for (DdlResult renameResult = result; renameResult != null; renameResult = renameResult.getRenameTableResult()) {
String schemaName0 = event.getDbName(); // 防止rename语句后产生schema变更带来影响
if (StringUtils.isNotEmpty(renameResult.getSchemaName())) {
schemaName0 = renameResult.getSchemaName();
}
tableName = renameResult.getTableName();
if (StringUtils.isNotEmpty(tableName)) {
// 如果解析到了正确的表信息,则根据全名进行清除
tableMetaCache.clearTableMeta(schemaName0, tableName);
} else {
// 如果无法解析正确的表信息,则根据schema进行清除
tableMetaCache.clearTableMetaWithSchemaName(schemaName0);
}
}
}
@@ -615,8 +623,9 @@ public class LogEventConvert extends AbstractCanalLifeCycle implements BinlogPar
if (column.getIsNull() && newValue == null) {
// 如果全是null
return false;
} else if (newValue != null && column.getValue().equals(newValue)) {
// 如果不围null,并且相等
} else if (newValue != null && (!column.getIsNull() && column.getValue().equals(newValue))) {
// fixed issue #135, old column is Null
// 如果不为null,并且相等
return false;
}
}

View File

@@ -23,15 +23,17 @@ import com.alibaba.otter.canal.protocol.CanalEntry.EventType;
*/
public class SimpleDdlParser {
public static final String CREATE_PATTERN = "^\\s*CREATE\\s*(TEMPORARY)?\\s*TABLE\\s*(.*)$";
public static final String DROP_PATTERN = "^\\s*DROP\\s*(TEMPORARY)?\\s*TABLE\\s*(.*)$";
public static final String ALERT_PATTERN = "^\\s*ALTER\\s*(IGNORE)?\\s*TABLE\\s*(.*)$";
public static final String TRUNCATE_PATTERN = "^\\s*TRUNCATE\\s*(TABLE)?\\s*(.*)$";
public static final String TABLE_PATTERN = "^(IF\\s*NOT\\s*EXISTS\\s*)?(IF\\s*EXISTS\\s*)?(`?.+?`?[;\\(\\s]+?)?.*$"; // 采用非贪婪模式
public static final String INSERT_PATTERN = "^\\s*(INSERT|MERGE|REPLACE)(.*)$";
public static final String UPDATE_PATTERN = "^\\s*UPDATE(.*)$";
public static final String DELETE_PATTERN = "^\\s*DELETE(.*)$";
public static final String RENAME_PATTERN = "^\\s*RENAME\\s*TABLE\\s*(.*?)\\s*TO\\s*(.*?)$";
public static final String CREATE_PATTERN = "^\\s*CREATE\\s*(TEMPORARY)?\\s*TABLE\\s*(.*)$";
public static final String DROP_PATTERN = "^\\s*DROP\\s*(TEMPORARY)?\\s*TABLE\\s*(.*)$";
public static final String ALERT_PATTERN = "^\\s*ALTER\\s*(IGNORE)?\\s*TABLE\\s*(.*)$";
public static final String TRUNCATE_PATTERN = "^\\s*TRUNCATE\\s*(TABLE)?\\s*(.*)$";
public static final String TABLE_PATTERN = "^(IF\\s*NOT\\s*EXISTS\\s*)?(IF\\s*EXISTS\\s*)?(`?.+?`?[;\\(\\s]+?)?.*$"; // 采用非贪婪模式
public static final String INSERT_PATTERN = "^\\s*(INSERT|MERGE|REPLACE)(.*)$";
public static final String UPDATE_PATTERN = "^\\s*UPDATE(.*)$";
public static final String DELETE_PATTERN = "^\\s*DELETE(.*)$";
public static final String RENAME_PATTERN = "^\\s*RENAME\\s+TABLE\\s+(.+?)\\s+TO\\s+(.+?)$";
public static final String RENAME_REMNANT_PATTERN = "^\\s*(.+?)\\s+TO\\s+(.+?)$";
/**
* <pre>
* CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
@@ -42,8 +44,8 @@ public class SimpleDdlParser {
* http://dev.mysql.com/doc/refman/5.6/en/create-index.html
* </pre>
*/
public static final String CREATE_INDEX_PATTERN = "^\\s*CREATE\\s*(UNIQUE)?(FULLTEXT)?(SPATIAL)?\\s*INDEX\\s*(.*?)\\s*ON\\s*(.*?)$";
public static final String DROP_INDEX_PATTERN = "^\\s*DROP\\s*INDEX\\s*(.*?)\\s*ON\\s*(.*?)$";
public static final String CREATE_INDEX_PATTERN = "^\\s*CREATE\\s*(UNIQUE)?(FULLTEXT)?(SPATIAL)?\\s*INDEX\\s*(.*?)\\s*ON\\s*(.*?)$";
public static final String DROP_INDEX_PATTERN = "^\\s*DROP\\s*INDEX\\s*(.*?)\\s*ON\\s*(.*?)$";
public static DdlResult parse(String queryString, String schmeaName) {
queryString = removeComment(queryString); // 去除/* */的sql注释内容
@@ -74,6 +76,18 @@ public class SimpleDdlParser {
result = parseRename(queryString, schmeaName, RENAME_PATTERN);
if (result != null) {
result.setType(EventType.RENAME);
String[] renameStrings = queryString.split(",");
if (renameStrings.length > 1) {
DdlResult lastResult = result;
for (int i = 1; i < renameStrings.length; i++) {
DdlResult ddlResult = parseRename(renameStrings[i], schmeaName, RENAME_REMNANT_PATTERN);
ddlResult.setType(EventType.RENAME);
lastResult.setRenameTableResult(ddlResult);
lastResult = ddlResult;
}
}
return result;
}
@@ -209,9 +223,15 @@ public class SimpleDdlParser {
private String schemaName;
private String tableName;
private String oriSchemaName; // rename ddl中的源表
private String oriTableName; // rename ddl中的目标表
private String oriSchemaName; // rename ddl中的源表
private String oriTableName; // rename ddl中的目标表
private EventType type;
private DdlResult renameTableResult; // 多个rename table的存储
/*
* RENAME TABLE tbl_name TO new_tbl_name [, tbl_name2 TO new_tbl_name2]
* ...
*/
public DdlResult(){
}
@@ -272,11 +292,28 @@ public class SimpleDdlParser {
this.oriTableName = oriTableName;
}
@Override
public String toString() {
return "DdlResult [schemaName=" + schemaName + ", tableName=" + tableName + ", oriSchemaName="
+ oriSchemaName + ", oriTableName=" + oriTableName + ", type=" + type + "]";
public DdlResult getRenameTableResult() {
return renameTableResult;
}
public void setRenameTableResult(DdlResult renameTableResult) {
this.renameTableResult = renameTableResult;
}
@Override
public String toString() {
DdlResult ddlResult = this;
StringBuffer sb = new StringBuffer();
do {
sb.append(String.format("DdlResult [schemaName=%s , tableName=%s , oriSchemaName=%s , oriTableName=%s , type=%s ];",
ddlResult.schemaName,
ddlResult.tableName,
ddlResult.oriSchemaName,
ddlResult.oriTableName,
ddlResult.type));
ddlResult = ddlResult.renameTableResult;
} while (ddlResult != null);
return sb.toString();
}
}
}

View File

@@ -149,6 +149,61 @@ public class SimpleDdlParserTest {
Assert.assertEquals("retl2", result.getSchemaName());
Assert.assertEquals("retl_mark", result.getOriTableName());
Assert.assertEquals("retl_mark2", result.getTableName());
queryString = "rename \n table \n `retl`.`retl_mark` to `retl2.retl_mark2` , `retl1`.`retl_mark1` to `retl3.retl_mark3`;";
result = SimpleDdlParser.parse(queryString, "retl");
Assert.assertNotNull(result);
Assert.assertEquals("retl", result.getOriSchemaName());
Assert.assertEquals("retl2", result.getSchemaName());
Assert.assertEquals("retl_mark", result.getOriTableName());
Assert.assertEquals("retl_mark2", result.getTableName());
result = result.getRenameTableResult();
Assert.assertNotNull(result);
Assert.assertEquals("retl1", result.getOriSchemaName());
Assert.assertEquals("retl3", result.getSchemaName());
Assert.assertEquals("retl_mark1", result.getOriTableName());
Assert.assertEquals("retl_mark3", result.getTableName());
//正则匹配test case
queryString = "rename table totl_mark to totl_mark2";
result = SimpleDdlParser.parse(queryString, "retl");
Assert.assertNotNull(result);
Assert.assertEquals("retl", result.getOriSchemaName());
Assert.assertEquals("retl", result.getSchemaName());
Assert.assertEquals("totl_mark", result.getOriTableName());
Assert.assertEquals("totl_mark2", result.getTableName());
queryString = "rename table totl.retl_mark to totl2.retl_mark2";
result = SimpleDdlParser.parse(queryString, "retl");
Assert.assertNotNull(result);
Assert.assertEquals("totl", result.getOriSchemaName());
Assert.assertEquals("totl2", result.getSchemaName());
Assert.assertEquals("retl_mark", result.getOriTableName());
Assert.assertEquals("retl_mark2", result.getTableName());
queryString = "rename \n table \n `totl`.`retl_mark` to `totl2.retl_mark2`;";
result = SimpleDdlParser.parse(queryString, "retl");
Assert.assertNotNull(result);
Assert.assertEquals("totl", result.getOriSchemaName());
Assert.assertEquals("totl2", result.getSchemaName());
Assert.assertEquals("retl_mark", result.getOriTableName());
Assert.assertEquals("retl_mark2", result.getTableName());
queryString = "rename \n table \n `totl`.`retl_mark` to `totl2.retl_mark2` , `totl1`.`retl_mark1` to `totl3.retl_mark3`;";
result = SimpleDdlParser.parse(queryString, "retl");
Assert.assertNotNull(result);
Assert.assertEquals("totl", result.getOriSchemaName());
Assert.assertEquals("totl2", result.getSchemaName());
Assert.assertEquals("retl_mark", result.getOriTableName());
Assert.assertEquals("retl_mark2", result.getTableName());
result = result.getRenameTableResult();
Assert.assertNotNull(result);
Assert.assertEquals("totl1", result.getOriSchemaName());
Assert.assertEquals("totl3", result.getSchemaName());
Assert.assertEquals("retl_mark1", result.getOriTableName());
Assert.assertEquals("retl_mark3", result.getTableName());
}
@Test

View File

@@ -4,7 +4,7 @@
<artifactId>canal</artifactId>
<packaging>pom</packaging>
<name>canal module for otter ${project.version}</name>
<version>1.0.20</version>
<version>1.0.21</version>
<url>https://github.com/alibaba/canal</url>
<parent>
<groupId>org.sonatype.oss</groupId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.alibaba.otter</groupId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>canal.server</artifactId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.alibaba.otter</groupId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.20</version>
<version>1.0.21</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.alibaba.otter</groupId>