mirror of
https://github.com/alibaba/canal.git
synced 2026-11-04 00:30:15 +08:00
fixed gtid
This commit is contained in:
@@ -189,6 +189,7 @@ public final class LogDecoder {
|
|||||||
/* updating position in context */
|
/* updating position in context */
|
||||||
logPosition.position = header.getLogPos();
|
logPosition.position = header.getLogPos();
|
||||||
event.fillTable(context);
|
event.fillTable(context);
|
||||||
|
header.putGtid(context.getGtidSet(), gtidLogEvent);
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
case LogEvent.UPDATE_ROWS_EVENT_V1: {
|
case LogEvent.UPDATE_ROWS_EVENT_V1: {
|
||||||
@@ -196,6 +197,7 @@ public final class LogDecoder {
|
|||||||
/* updating position in context */
|
/* updating position in context */
|
||||||
logPosition.position = header.getLogPos();
|
logPosition.position = header.getLogPos();
|
||||||
event.fillTable(context);
|
event.fillTable(context);
|
||||||
|
header.putGtid(context.getGtidSet(), gtidLogEvent);
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
case LogEvent.DELETE_ROWS_EVENT_V1: {
|
case LogEvent.DELETE_ROWS_EVENT_V1: {
|
||||||
@@ -203,6 +205,7 @@ public final class LogDecoder {
|
|||||||
/* updating position in context */
|
/* updating position in context */
|
||||||
logPosition.position = header.getLogPos();
|
logPosition.position = header.getLogPos();
|
||||||
event.fillTable(context);
|
event.fillTable(context);
|
||||||
|
header.putGtid(context.getGtidSet(), gtidLogEvent);
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
case LogEvent.ROTATE_EVENT: {
|
case LogEvent.ROTATE_EVENT: {
|
||||||
|
|||||||
@@ -8,6 +8,15 @@ import java.sql.Statement;
|
|||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.taobao.tddl.dbsync.binlog.event.DeleteRowsLogEvent;
|
||||||
|
import com.taobao.tddl.dbsync.binlog.event.QueryLogEvent;
|
||||||
|
import com.taobao.tddl.dbsync.binlog.event.RotateLogEvent;
|
||||||
|
import com.taobao.tddl.dbsync.binlog.event.RowsQueryLogEvent;
|
||||||
|
import com.taobao.tddl.dbsync.binlog.event.UpdateRowsLogEvent;
|
||||||
|
import com.taobao.tddl.dbsync.binlog.event.WriteRowsLogEvent;
|
||||||
|
import com.taobao.tddl.dbsync.binlog.event.XidLogEvent;
|
||||||
|
import com.taobao.tddl.dbsync.binlog.event.mariadb.AnnotateRowsEvent;
|
||||||
|
|
||||||
public class DirectLogFetcherTest extends BaseLogFetcherTest {
|
public class DirectLogFetcherTest extends BaseLogFetcherTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -15,54 +24,49 @@ public class DirectLogFetcherTest extends BaseLogFetcherTest {
|
|||||||
DirectLogFetcher fecther = new DirectLogFetcher();
|
DirectLogFetcher fecther = new DirectLogFetcher();
|
||||||
try {
|
try {
|
||||||
Class.forName("com.mysql.jdbc.Driver");
|
Class.forName("com.mysql.jdbc.Driver");
|
||||||
Connection connection = DriverManager.getConnection("jdbc:mysql://100.81.154.142:3306", "root", "hello");
|
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306", "root", "hello");
|
||||||
Statement statement = connection.createStatement();
|
Statement statement = connection.createStatement();
|
||||||
statement.execute("SET @master_binlog_checksum='@@global.binlog_checksum'");
|
statement.execute("SET @master_binlog_checksum='@@global.binlog_checksum'");
|
||||||
statement.execute("SET @mariadb_slave_capability='" + LogEvent.MARIA_SLAVE_CAPABILITY_MINE + "'");
|
statement.execute("SET @mariadb_slave_capability='" + LogEvent.MARIA_SLAVE_CAPABILITY_MINE + "'");
|
||||||
|
|
||||||
fecther.open(connection, "mysql-bin.000006", 120L, 2);
|
fecther.open(connection, "mysql-bin.000007", 89797036L, 2);
|
||||||
|
|
||||||
LogDecoder decoder = new LogDecoder(LogEvent.UNKNOWN_EVENT, LogEvent.UNKNOWN_EVENT);
|
LogDecoder decoder = new LogDecoder(LogEvent.UNKNOWN_EVENT, LogEvent.ENUM_END_EVENT);
|
||||||
LogContext context = new LogContext();
|
LogContext context = new LogContext();
|
||||||
while (fecther.fetch()) {
|
while (fecther.fetch()) {
|
||||||
decoder.decode(fecther, context);
|
LogEvent event = decoder.decode(fecther, context);
|
||||||
continue;
|
int eventType = event.getHeader().getType();
|
||||||
// if (event == null) {
|
switch (eventType) {
|
||||||
// continue;
|
case LogEvent.ROTATE_EVENT:
|
||||||
// }
|
binlogFileName = ((RotateLogEvent) event).getFilename();
|
||||||
//
|
break;
|
||||||
// int eventType = event.getHeader().getType();
|
case LogEvent.WRITE_ROWS_EVENT_V1:
|
||||||
// switch (eventType) {
|
case LogEvent.WRITE_ROWS_EVENT:
|
||||||
// case LogEvent.ROTATE_EVENT:
|
parseRowsEvent((WriteRowsLogEvent) event);
|
||||||
// binlogFileName = ((RotateLogEvent) event).getFilename();
|
break;
|
||||||
// break;
|
case LogEvent.UPDATE_ROWS_EVENT_V1:
|
||||||
// case LogEvent.WRITE_ROWS_EVENT_V1:
|
case LogEvent.UPDATE_ROWS_EVENT:
|
||||||
// case LogEvent.WRITE_ROWS_EVENT:
|
parseRowsEvent((UpdateRowsLogEvent) event);
|
||||||
// parseRowsEvent((WriteRowsLogEvent) event);
|
break;
|
||||||
// break;
|
case LogEvent.DELETE_ROWS_EVENT_V1:
|
||||||
// case LogEvent.UPDATE_ROWS_EVENT_V1:
|
case LogEvent.DELETE_ROWS_EVENT:
|
||||||
// case LogEvent.UPDATE_ROWS_EVENT:
|
parseRowsEvent((DeleteRowsLogEvent) event);
|
||||||
// parseRowsEvent((UpdateRowsLogEvent) event);
|
break;
|
||||||
// break;
|
case LogEvent.QUERY_EVENT:
|
||||||
// case LogEvent.DELETE_ROWS_EVENT_V1:
|
parseQueryEvent((QueryLogEvent) event);
|
||||||
// case LogEvent.DELETE_ROWS_EVENT:
|
break;
|
||||||
// parseRowsEvent((DeleteRowsLogEvent) event);
|
case LogEvent.ROWS_QUERY_LOG_EVENT:
|
||||||
// break;
|
parseRowsQueryEvent((RowsQueryLogEvent) event);
|
||||||
// case LogEvent.QUERY_EVENT:
|
break;
|
||||||
// parseQueryEvent((QueryLogEvent) event);
|
case LogEvent.ANNOTATE_ROWS_EVENT:
|
||||||
// break;
|
parseAnnotateRowsEvent((AnnotateRowsEvent) event);
|
||||||
// case LogEvent.ROWS_QUERY_LOG_EVENT:
|
break;
|
||||||
// parseRowsQueryEvent((RowsQueryLogEvent) event);
|
case LogEvent.XID_EVENT:
|
||||||
// break;
|
parseXidEvent((XidLogEvent) event);
|
||||||
// case LogEvent.ANNOTATE_ROWS_EVENT:
|
break;
|
||||||
// parseAnnotateRowsEvent((AnnotateRowsEvent) event);
|
default:
|
||||||
// break;
|
break;
|
||||||
// case LogEvent.XID_EVENT:
|
}
|
||||||
// parseXidEvent((XidLogEvent) event);
|
|
||||||
// break;
|
|
||||||
// default:
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|||||||
@@ -25,6 +25,4 @@ public interface MultiStageCoprocessor extends CanalLifeCycle {
|
|||||||
public boolean publish(LogBuffer buffer);
|
public boolean publish(LogBuffer buffer);
|
||||||
|
|
||||||
public boolean publish(LogEvent event);
|
public boolean publish(LogEvent event);
|
||||||
|
|
||||||
public void reset();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ import com.taobao.tddl.dbsync.binlog.event.RowsLogEvent;
|
|||||||
import com.taobao.tddl.dbsync.binlog.event.UpdateRowsLogEvent;
|
import com.taobao.tddl.dbsync.binlog.event.UpdateRowsLogEvent;
|
||||||
import com.taobao.tddl.dbsync.binlog.event.WriteRowsLogEvent;
|
import com.taobao.tddl.dbsync.binlog.event.WriteRowsLogEvent;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 针对解析器提供一个多阶段协同的处理
|
* 针对解析器提供一个多阶段协同的处理
|
||||||
*
|
*
|
||||||
@@ -53,21 +52,21 @@ import com.taobao.tddl.dbsync.binlog.event.WriteRowsLogEvent;
|
|||||||
*/
|
*/
|
||||||
public class MysqlMultiStageCoprocessor extends AbstractCanalLifeCycle implements MultiStageCoprocessor {
|
public class MysqlMultiStageCoprocessor extends AbstractCanalLifeCycle implements MultiStageCoprocessor {
|
||||||
|
|
||||||
private static final int maxFullTimes = 10;
|
private static final int maxFullTimes = 10;
|
||||||
private LogEventConvert logEventConvert;
|
private LogEventConvert logEventConvert;
|
||||||
private EventTransactionBuffer transactionBuffer;
|
private EventTransactionBuffer transactionBuffer;
|
||||||
private ErosaConnection connection;
|
private ErosaConnection connection;
|
||||||
|
|
||||||
private int parserThreadCount;
|
private int parserThreadCount;
|
||||||
private int ringBufferSize;
|
private int ringBufferSize;
|
||||||
private RingBuffer<MessageEvent> disruptorMsgBuffer;
|
private RingBuffer<MessageEvent> disruptorMsgBuffer;
|
||||||
private ExecutorService parserExecutor;
|
private ExecutorService parserExecutor;
|
||||||
private ExecutorService stageExecutor;
|
private ExecutorService stageExecutor;
|
||||||
private String destination;
|
private String destination;
|
||||||
private volatile CanalParseException exception;
|
private volatile CanalParseException exception;
|
||||||
private AtomicLong eventsPublishBlockingTime;
|
private AtomicLong eventsPublishBlockingTime;
|
||||||
private GTIDSet gtidSet;
|
private GTIDSet gtidSet;
|
||||||
private WorkerPool<MessageEvent> workerPool;
|
private WorkerPool<MessageEvent> workerPool;
|
||||||
private BatchEventProcessor<MessageEvent> simpleParserStage;
|
private BatchEventProcessor<MessageEvent> simpleParserStage;
|
||||||
private BatchEventProcessor<MessageEvent> sinkStoreStage;
|
private BatchEventProcessor<MessageEvent> sinkStoreStage;
|
||||||
|
|
||||||
@@ -235,15 +234,6 @@ public class MysqlMultiStageCoprocessor extends AbstractCanalLifeCycle implement
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset() {
|
|
||||||
if (isStart()) {
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SimpleParserStage implements EventHandler<MessageEvent>, LifecycleAware {
|
private class SimpleParserStage implements EventHandler<MessageEvent>, LifecycleAware {
|
||||||
|
|
||||||
private LogDecoder decoder;
|
private LogDecoder decoder;
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||||||
import java.util.concurrent.locks.Condition;
|
import java.util.concurrent.locks.Condition;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.protocol.CanalEntry;
|
import com.alibaba.otter.canal.protocol.CanalEntry;
|
||||||
import com.alibaba.otter.canal.protocol.CanalEntry.EventType;
|
import com.alibaba.otter.canal.protocol.CanalEntry.EventType;
|
||||||
import com.alibaba.otter.canal.protocol.position.LogPosition;
|
import com.alibaba.otter.canal.protocol.position.LogPosition;
|
||||||
@@ -37,14 +39,14 @@ public class MemoryEventStoreWithBuffer extends AbstractCanalStoreScavenge imple
|
|||||||
|
|
||||||
private static final long INIT_SEQUENCE = -1;
|
private static final long INIT_SEQUENCE = -1;
|
||||||
private int bufferSize = 16 * 1024;
|
private int bufferSize = 16 * 1024;
|
||||||
private int bufferMemUnit = 1024; // memsize的单位,默认为1kb大小
|
private int bufferMemUnit = 1024; // memsize的单位,默认为1kb大小
|
||||||
private int indexMask;
|
private int indexMask;
|
||||||
private Event[] entries;
|
private Event[] entries;
|
||||||
|
|
||||||
// 记录下put/get/ack操作的三个下标
|
// 记录下put/get/ack操作的三个下标
|
||||||
private AtomicLong putSequence = new AtomicLong(INIT_SEQUENCE); // 代表当前put操作最后一次写操作发生的位置
|
private AtomicLong putSequence = new AtomicLong(INIT_SEQUENCE); // 代表当前put操作最后一次写操作发生的位置
|
||||||
private AtomicLong getSequence = new AtomicLong(INIT_SEQUENCE); // 代表当前get操作读取的最后一条的位置
|
private AtomicLong getSequence = new AtomicLong(INIT_SEQUENCE); // 代表当前get操作读取的最后一条的位置
|
||||||
private AtomicLong ackSequence = new AtomicLong(INIT_SEQUENCE); // 代表当前ack操作的最后一条的位置
|
private AtomicLong ackSequence = new AtomicLong(INIT_SEQUENCE); // 代表当前ack操作的最后一条的位置
|
||||||
|
|
||||||
// 记录下put/get/ack操作的三个memsize大小
|
// 记录下put/get/ack操作的三个memsize大小
|
||||||
private AtomicLong putMemSize = new AtomicLong(0);
|
private AtomicLong putMemSize = new AtomicLong(0);
|
||||||
@@ -66,7 +68,7 @@ public class MemoryEventStoreWithBuffer extends AbstractCanalStoreScavenge imple
|
|||||||
private Condition notFull = lock.newCondition();
|
private Condition notFull = lock.newCondition();
|
||||||
private Condition notEmpty = lock.newCondition();
|
private Condition notEmpty = lock.newCondition();
|
||||||
|
|
||||||
private BatchMode batchMode = BatchMode.ITEMSIZE; // 默认为内存大小模式
|
private BatchMode batchMode = BatchMode.ITEMSIZE; // 默认为内存大小模式
|
||||||
private boolean ddlIsolation = false;
|
private boolean ddlIsolation = false;
|
||||||
|
|
||||||
public MemoryEventStoreWithBuffer(){
|
public MemoryEventStoreWithBuffer(){
|
||||||
@@ -335,7 +337,8 @@ public class MemoryEventStoreWithBuffer extends AbstractCanalStoreScavenge imple
|
|||||||
|
|
||||||
for (int i = entrys.size() - 1; i >= 0; i--) {
|
for (int i = entrys.size() - 1; i >= 0; i--) {
|
||||||
Event event = entrys.get(i);
|
Event event = entrys.get(i);
|
||||||
if (CanalEntry.EntryType.TRANSACTIONBEGIN == event.getEntryType()
|
// GTID模式,ack的位点必须是事务结尾,因为下一次订阅的时候mysql会发送这个gtid之后的next,如果在事务头就记录了会丢这最后一个事务
|
||||||
|
if ((CanalEntry.EntryType.TRANSACTIONBEGIN == event.getEntryType() && StringUtils.isEmpty(event.getGtid()))
|
||||||
|| CanalEntry.EntryType.TRANSACTIONEND == event.getEntryType() || isDdl(event.getEventType())) {
|
|| CanalEntry.EntryType.TRANSACTIONEND == event.getEntryType() || isDdl(event.getEventType())) {
|
||||||
// 将事务头/尾设置可被为ack的点
|
// 将事务头/尾设置可被为ack的点
|
||||||
range.setAck(CanalEventUtils.createPosition(event));
|
range.setAck(CanalEventUtils.createPosition(event));
|
||||||
|
|||||||
Reference in New Issue
Block a user