Skip to content

Commit 2b595b1

Browse files
author
Shlomi Noach
authored
Merge pull request #196 from github/concurrent-rowcount
concurrent row-count
2 parents 59967d5 + c7edd1e commit 2b595b1

File tree

5 files changed

+30
-11
lines changed

5 files changed

+30
-11
lines changed

go/base/context.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ type MigrationContext struct {
4949
AlterStatement string
5050

5151
CountTableRows bool
52+
ConcurrentCountTableRows bool
5253
AllowedRunningOnMaster bool
5354
AllowedMasterMaster bool
5455
SwitchToRowBinlogFormat bool
@@ -94,6 +95,7 @@ type MigrationContext struct {
9495

9596
TableEngine string
9697
RowsEstimate int64
98+
RowsDeltaEstimate int64
9799
UsedRowsEstimateMethod RowsEstimateMethod
98100
HasSuperPrivilege bool
99101
OriginalBinlogFormat string

go/cmd/gh-ost/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ func main() {
5353
flag.StringVar(&migrationContext.OriginalTableName, "table", "", "table name (mandatory)")
5454
flag.StringVar(&migrationContext.AlterStatement, "alter", "", "alter statement (mandatory)")
5555
flag.BoolVar(&migrationContext.CountTableRows, "exact-rowcount", false, "actually count table rows as opposed to estimate them (results in more accurate progress estimation)")
56+
flag.BoolVar(&migrationContext.ConcurrentCountTableRows, "concurrent-rowcount", false, "(with --exact-rowcount), when true: count rows after row-copy begins, concurrently, and adjust row estimate later on; defaults false: first count rows, then start row copy")
5657
flag.BoolVar(&migrationContext.AllowedRunningOnMaster, "allow-on-master", false, "allow this migration to run directly on master. Preferably it would run on a replica")
5758
flag.BoolVar(&migrationContext.AllowedMasterMaster, "allow-master-master", false, "explicitly allow running in a master-master setup")
5859
flag.BoolVar(&migrationContext.NullableUniqueKeyAllowed, "allow-nullable-unique-key", false, "allow gh-ost to migrate based on a unique key with nullable columns. As long as no NULL values exist, this should be OK. If NULL values exist in chosen key, data may be corrupted. Use at your own risk!")

go/logic/applier.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ func (this *Applier) ApplyDMLEventQuery(dmlEvent *binlog.BinlogDMLEvent) error {
893893
// no error
894894
atomic.AddInt64(&this.migrationContext.TotalDMLEventsApplied, 1)
895895
if this.migrationContext.CountTableRows {
896-
atomic.AddInt64(&this.migrationContext.RowsEstimate, rowDelta)
896+
atomic.AddInt64(&this.migrationContext.RowsDeltaEstimate, rowDelta)
897897
}
898898
return nil
899899
}

go/logic/inspect.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,12 +440,14 @@ func (this *Inspector) CountTableRows() error {
440440
log.Infof("As instructed, I'm issuing a SELECT COUNT(*) on the table. This may take a while")
441441

442442
query := fmt.Sprintf(`select /* gh-ost */ count(*) as rows from %s.%s`, sql.EscapeName(this.migrationContext.DatabaseName), sql.EscapeName(this.migrationContext.OriginalTableName))
443-
if err := this.db.QueryRow(query).Scan(&this.migrationContext.RowsEstimate); err != nil {
443+
var rowsEstimate int64
444+
if err := this.db.QueryRow(query).Scan(&rowsEstimate); err != nil {
444445
return err
445446
}
447+
atomic.StoreInt64(&this.migrationContext.RowsEstimate, rowsEstimate)
446448
this.migrationContext.UsedRowsEstimateMethod = base.CountRowsEstimate
447449

448-
log.Infof("Exact number of rows via COUNT: %d", this.migrationContext.RowsEstimate)
450+
log.Infof("Exact number of rows via COUNT: %d", rowsEstimate)
449451

450452
return nil
451453
}

go/logic/migrator.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,24 @@ func (this *Migrator) validateStatement() (err error) {
361361
return nil
362362
}
363363

364+
func (this *Migrator) countTableRows() (err error) {
365+
if !this.migrationContext.CountTableRows {
366+
// Not counting; we stay with an estimate
367+
return nil
368+
}
369+
if this.migrationContext.Noop {
370+
log.Debugf("Noop operation; not really counting table rows")
371+
return nil
372+
}
373+
if this.migrationContext.ConcurrentCountTableRows {
374+
go this.inspector.CountTableRows()
375+
log.Infof("As instructed, counting rows in the background; meanwhile I will use an estimated count, and will update it later on")
376+
// and we ignore errors, because this turns to be a background job
377+
return nil
378+
}
379+
return this.inspector.CountTableRows()
380+
}
381+
364382
// Migrate executes the complete migration logic. This is *the* major gh-ost function.
365383
func (this *Migrator) Migrate() (err error) {
366384
log.Infof("Migrating %s.%s", sql.EscapeName(this.migrationContext.DatabaseName), sql.EscapeName(this.migrationContext.OriginalTableName))
@@ -402,12 +420,8 @@ func (this *Migrator) Migrate() (err error) {
402420
}
403421
defer this.server.RemoveSocketFile()
404422

405-
if this.migrationContext.CountTableRows {
406-
if this.migrationContext.Noop {
407-
log.Debugf("Noop operation; not really counting table rows")
408-
} else if err := this.inspector.CountTableRows(); err != nil {
409-
return err
410-
}
423+
if err := this.countTableRows(); err != nil {
424+
return err
411425
}
412426

413427
if err := this.addDMLEventsListener(); err != nil {
@@ -948,7 +962,7 @@ func (this *Migrator) printStatus(rule PrintStatusRule, writers ...io.Writer) {
948962
elapsedTime := this.migrationContext.ElapsedTime()
949963
elapsedSeconds := int64(elapsedTime.Seconds())
950964
totalRowsCopied := this.migrationContext.GetTotalRowsCopied()
951-
rowsEstimate := atomic.LoadInt64(&this.migrationContext.RowsEstimate)
965+
rowsEstimate := atomic.LoadInt64(&this.migrationContext.RowsEstimate) + atomic.LoadInt64(&this.migrationContext.RowsDeltaEstimate)
952966
var progressPct float64
953967
if rowsEstimate == 0 {
954968
progressPct = 100.0
@@ -970,7 +984,7 @@ func (this *Migrator) printStatus(rule PrintStatusRule, writers ...io.Writer) {
970984

971985
var etaSeconds float64 = math.MaxFloat64
972986
eta := "N/A"
973-
if atomic.LoadInt64(&this.migrationContext.CountingRowsFlag) > 0 {
987+
if atomic.LoadInt64(&this.migrationContext.CountingRowsFlag) > 0 && !this.migrationContext.ConcurrentCountTableRows {
974988
eta = "counting rows"
975989
} else if atomic.LoadInt64(&this.migrationContext.IsPostponingCutOver) > 0 {
976990
eta = "postponing cut-over"

0 commit comments

Comments
 (0)