You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If a insert operation flushed to binlog and waiting for a ACK from slave, then gh-ost run addDMLEventsListener and start apply binlog , the insert binlog will not applied by applier thread because insert binlog pos may has processed, and if this insert commited after gh-ost run ReadMigrationRangeValues , this insert data will not in the MigrationRange, then this insert data lost.
How to repeat:
This bug is hard to repeat in simple way.
Modify gh-ost code and add some test code , place a sleep before addDMLEventsListener to make it easy to repeat.
if err := this.countTableRows(); err != nil {
return err
}
// for test
time.Sleep(30*time.Second)
if err := this.addDMLEventsListener(); err != nil {
return err
}
if err := this.applier.ReadMigrationRangeValues(); err != nil {
return err
}
create a semi-sync(after_sync) mysql master-backup, set rpl_semi_sync_master_timeout=150000;
create table t(id int auto_increment ,primary key(id));
insert into t set id=1;
run gh-ost alter table : alter table t engine=innnodb, when ghc/gho table created and run at the Sleep above, run 'stop slave io_thread' on mysql backup, then insert into t set id=2 on the mysql master, now master will flush id=2 binlog and waiting for ACK from backup
after about 30 seconds, the gh-ost will continue addDMLEventsListener and ReadMigrationRangeValues, now the id=2 trx still waiting for ACK and not commit in Innodb, data lost happen.
after the ddl , id=2 row will not in table t, data lost.
Suggest fix:
After addDMLEventsListener, add a insert OP to GHC table and read from the table ,if insert OK and read data from the table OK, all binlog flushed but not finish commit before addDMLEventsListener commited.
if err := this.addDMLEventsListener(); err != nil {
return err
}
// after add events listener, we need wait all binlog flushed before add listener to commit before read range.
// by insert a single row into ghc table and read it out.
if err := this.WaitAllBinlogCommit(); err != nil {
return err
}
if err := this.applier.ReadMigrationRangeValues(); err != nil {
return err
}
The text was updated successfully, but these errors were encountered:
When MySQL semi-sync after_sync enabled, data may lost after DDL in the follow position:
migrator.go
If a
insert
operation flushed to binlog and waiting for a ACK from slave, then gh-ost runaddDMLEventsListener
and start apply binlog , theinsert
binlog will not applied by applier thread becauseinsert
binlog pos may has processed, and if thisinsert
commited after gh-ost runReadMigrationRangeValues
, thisinsert
data will not in the MigrationRange, then thisinsert
data lost.How to repeat:
This bug is hard to repeat in simple way.
Modify gh-ost code and add some test code , place a sleep before addDMLEventsListener to make it easy to repeat.
insert into t set id=2
on the mysql master, now master will flush id=2 binlog and waiting for ACK from backupaddDMLEventsListener
andReadMigrationRangeValues
, now theid=2
trx still waiting for ACK and not commit in Innodb, data lost happen.id=2
row will not in tablet
, data lost.Suggest fix:
After
addDMLEventsListener
, add a insert OP to GHC table and read from the table ,if insert OK and read data from the table OK, all binlog flushed but not finish commit beforeaddDMLEventsListener
commited.The text was updated successfully, but these errors were encountered: