mirror of
https://github.com/alibaba/canal.git
synced 2026-11-04 00:30:15 +08:00
fixed issue #539 , support bio&netty
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
package com.alibaba.otter.canal.parse.inbound.mysql;
|
||||
|
||||
import static com.alibaba.otter.canal.parse.inbound.mysql.dbsync.DirectLogFetcher.MASTER_HEARTBEAT_PERIOD_SECONDS;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
@@ -29,8 +30,6 @@ import com.taobao.tddl.dbsync.binlog.LogContext;
|
||||
import com.taobao.tddl.dbsync.binlog.LogDecoder;
|
||||
import com.taobao.tddl.dbsync.binlog.LogEvent;
|
||||
|
||||
import static com.alibaba.otter.canal.parse.inbound.mysql.dbsync.DirectLogFetcher.MASTER_HEARTBEAT_PERIOD_SECONDS;
|
||||
|
||||
public class MysqlConnection implements ErosaConnection {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MysqlConnection.class);
|
||||
@@ -298,10 +297,12 @@ public class MysqlConnection implements ErosaConnection {
|
||||
}
|
||||
|
||||
/**
|
||||
* MASTER_HEARTBEAT_PERIOD sets the interval in seconds between replication heartbeats.
|
||||
* Whenever the master's binary log is updated with an event, the waiting period for the next heartbeat is reset.
|
||||
* interval is a decimal value having the range 0 to 4294967 seconds and a resolution in milliseconds;
|
||||
* the smallest nonzero value is 0.001. Heartbeats are sent by the master only if there are no unsent events
|
||||
* MASTER_HEARTBEAT_PERIOD sets the interval in seconds between
|
||||
* replication heartbeats. Whenever the master's binary log is updated
|
||||
* with an event, the waiting period for the next heartbeat is reset.
|
||||
* interval is a decimal value having the range 0 to 4294967 seconds and
|
||||
* a resolution in milliseconds; the smallest nonzero value is 0.001.
|
||||
* Heartbeats are sent by the master only if there are no unsent events
|
||||
* in the binary log file for a period longer than interval.
|
||||
*/
|
||||
try {
|
||||
|
||||
@@ -23,8 +23,8 @@ public class DirectLogFetcher extends LogFetcher {
|
||||
|
||||
// Master heartbeat interval
|
||||
public static final int MASTER_HEARTBEAT_PERIOD_SECONDS = 15;
|
||||
// +1s 确保 timeout > heartbeat interval
|
||||
private static final int READ_TIMEOUT_MILLISECONDS = (MASTER_HEARTBEAT_PERIOD_SECONDS + 1) * 1000;
|
||||
// +10s 确保 timeout > heartbeat interval
|
||||
private static final int READ_TIMEOUT_MILLISECONDS = (MASTER_HEARTBEAT_PERIOD_SECONDS + 10) * 1000;
|
||||
|
||||
/** Command to dump binlog */
|
||||
public static final byte COM_BINLOG_DUMP = 18;
|
||||
|
||||
@@ -2,15 +2,19 @@ package com.alibaba.otter.canal.parse.inbound.mysql.dbsync;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.alibaba.otter.canal.parse.driver.mysql.packets.server.FieldPacket;
|
||||
import com.alibaba.otter.canal.parse.driver.mysql.packets.server.ResultSetPacket;
|
||||
import com.alibaba.otter.canal.parse.exception.CanalParseException;
|
||||
import com.alibaba.otter.canal.parse.inbound.TableMeta;
|
||||
import com.alibaba.otter.canal.parse.inbound.TableMeta.FieldMeta;
|
||||
import com.alibaba.otter.canal.parse.inbound.mysql.MysqlConnection;
|
||||
import com.alibaba.otter.canal.parse.inbound.mysql.ddl.DruidDdlParser;
|
||||
import com.alibaba.otter.canal.parse.inbound.mysql.tsdb.DatabaseTableMeta;
|
||||
import com.alibaba.otter.canal.parse.inbound.mysql.tsdb.MemoryTableMeta;
|
||||
import com.alibaba.otter.canal.parse.inbound.mysql.tsdb.TableMetaTSDB;
|
||||
@@ -75,14 +79,22 @@ public class TableMetaCache {
|
||||
}
|
||||
|
||||
private TableMeta getTableMetaByDB(String fullname) throws IOException {
|
||||
ResultSetPacket packet = connection.query("show create table " + fullname);
|
||||
String[] names = StringUtils.split(fullname, "`.`");
|
||||
String schema = names[0];
|
||||
String table = names[1].substring(0, names[1].length());
|
||||
return new TableMeta(schema, table, parserTableMeta(schema, table, packet));
|
||||
try {
|
||||
ResultSetPacket packet = connection.query("show create table " + fullname);
|
||||
String[] names = StringUtils.split(fullname, "`.`");
|
||||
String schema = names[0];
|
||||
String table = names[1].substring(0, names[1].length());
|
||||
return new TableMeta(schema, table, parseTableMeta(schema, table, packet));
|
||||
} catch (Throwable e) { // fallback to desc table
|
||||
ResultSetPacket packet = connection.query("desc " + fullname);
|
||||
String[] names = StringUtils.split(fullname, "`.`");
|
||||
String schema = names[0];
|
||||
String table = names[1].substring(0, names[1].length());
|
||||
return new TableMeta(schema, table, parseTableMetaByDesc(packet));
|
||||
}
|
||||
}
|
||||
|
||||
public static List<FieldMeta> parserTableMeta(String schema, String table, ResultSetPacket packet) {
|
||||
public static List<FieldMeta> parseTableMeta(String schema, String table, ResultSetPacket packet) {
|
||||
if (packet.getFieldValues().size() > 1) {
|
||||
String createDDL = packet.getFieldValues().get(1);
|
||||
MemoryTableMeta memoryTableMeta = new MemoryTableMeta();
|
||||
@@ -94,6 +106,40 @@ public class TableMetaCache {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理desc table的结果
|
||||
*/
|
||||
public static List<FieldMeta> parseTableMetaByDesc(ResultSetPacket packet) {
|
||||
Map<String, Integer> nameMaps = new HashMap<String, Integer>(6, 1f);
|
||||
int index = 0;
|
||||
for (FieldPacket fieldPacket : packet.getFieldDescriptors()) {
|
||||
nameMaps.put(fieldPacket.getOriginalName(), index++);
|
||||
}
|
||||
|
||||
int size = packet.getFieldDescriptors().size();
|
||||
int count = packet.getFieldValues().size() / packet.getFieldDescriptors().size();
|
||||
List<FieldMeta> result = new ArrayList<FieldMeta>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
FieldMeta meta = new FieldMeta();
|
||||
// 做一个优化,使用String.intern(),共享String对象,减少内存使用
|
||||
meta.setColumnName(packet.getFieldValues().get(nameMaps.get(COLUMN_NAME) + i * size).intern());
|
||||
meta.setColumnType(packet.getFieldValues().get(nameMaps.get(COLUMN_TYPE) + i * size));
|
||||
meta.setNullable(StringUtils.equalsIgnoreCase(packet.getFieldValues().get(nameMaps.get(IS_NULLABLE) + i
|
||||
* size),
|
||||
"YES"));
|
||||
meta.setKey("PRI".equalsIgnoreCase(packet.getFieldValues().get(nameMaps.get(COLUMN_KEY) + i * size)));
|
||||
meta.setUnique("UNI".equalsIgnoreCase(packet.getFieldValues().get(nameMaps.get(COLUMN_KEY) + i * size)));
|
||||
// 特殊处理引号
|
||||
meta.setDefaultValue(DruidDdlParser.unescapeQuotaName(packet.getFieldValues()
|
||||
.get(nameMaps.get(COLUMN_DEFAULT) + i * size)));
|
||||
meta.setExtra(packet.getFieldValues().get(nameMaps.get(EXTRA) + i * size));
|
||||
|
||||
result.add(meta);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public TableMeta getTableMeta(String schema, String table) {
|
||||
return getTableMeta(schema, table, true);
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ public class DatabaseTableMeta implements TableMetaTSDB {
|
||||
ResultSetPacket packet = connection.query("show create table " + getFullName(schema, table));
|
||||
if (packet.getFieldValues().size() > 1) {
|
||||
createDDL = packet.getFieldValues().get(1);
|
||||
tableMetaFromDB.setFields(TableMetaCache.parserTableMeta(schema, table, packet));
|
||||
tableMetaFromDB.setFields(TableMetaCache.parseTableMeta(schema, table, packet));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (e.getMessage().contains("errorNumber=1146")) {
|
||||
|
||||
Reference in New Issue
Block a user