@@ -581,7 +581,14 @@ func (td *tableDiffer) diff(ctx context.Context, coreOpts *tabletmanagerdatapb.V
581581 maxReportSampleRows := reportOpts .GetMaxSampleRows ()
582582
583583 for {
584- lastProcessedRow = sourceRow
584+ // Only advance the persisted position when the previous iteration
585+ // consumed the held source row (advanceSource still holds that
586+ // iteration's decision here). After an extra-target-row iteration the
587+ // held source row has not been processed yet, and recording it as
588+ // lastpk would make a resumed diff skip it permanently.
589+ if advanceSource {
590+ lastProcessedRow = sourceRow
591+ }
585592
586593 select {
587594 case <- ctx .Done ():
@@ -629,35 +636,60 @@ func (td *tableDiffer) diff(ctx context.Context, coreOpts *tabletmanagerdatapb.V
629636 advanceSource = true
630637 advanceTarget = true
631638 if sourceRow == nil {
632- diffRow , err := td .genRowDiff (td .tablePlan .sourceQuery , targetRow , reportOpts )
633- if err != nil {
634- return nil , vterrors .Wrap (err , "unexpected error generating diff" )
635- }
636- dr .ExtraRowsTargetDiffs = append (dr .ExtraRowsTargetDiffs , diffRow )
637-
638- // Drain target, update count.
639- count , err := targetExecutor .drain (ctx )
640- if err != nil {
641- return nil , err
639+ // No more rows from the source; drain the remaining target rows,
640+ // saving a sample for each one (up to maxExtraRowsToCompare) so that
641+ // reconcileExtraRows can match them against any extra source rows.
642+ // Counting drained rows without saving a sample makes them impossible
643+ // to reconcile, producing false positive extra rows in the report.
644+ // The drained rows are merged into the report only after the full
645+ // drain succeeds: they are beyond the persisted lastpk, so partially
646+ // counted rows would be counted again when a failed diff is resumed.
647+ drainedRows := int64 (0 )
648+ var drainedDiffs []* RowDiff
649+ for targetRow != nil {
650+ if dr .ExtraRowsTarget + drainedRows < maxExtraRowsToCompare {
651+ diffRow , err := td .genRowDiff (td .tablePlan .targetQuery , targetRow , reportOpts )
652+ if err != nil {
653+ return nil , vterrors .Wrap (err , "unexpected error generating diff" )
654+ }
655+ drainedDiffs = append (drainedDiffs , diffRow )
656+ }
657+ drainedRows ++
658+ targetRow , err = targetExecutor .next ()
659+ if err != nil {
660+ return nil , err
661+ }
642662 }
643- dr .ExtraRowsTarget += 1 + count
644- dr .ProcessedRows += 1 + count
663+ dr .ExtraRowsTarget += drainedRows
664+ dr .ProcessedRows += drainedRows
665+ dr .ExtraRowsTargetDiffs = append (dr .ExtraRowsTargetDiffs , drainedDiffs ... )
645666 return dr , nil
646667 }
647668 if targetRow == nil {
648- // No more rows from the target but we know we have more rows from
649- // source, so drain them and update the counts.
650- diffRow , err := td .genRowDiff (td .tablePlan .sourceQuery , sourceRow , reportOpts )
651- if err != nil {
652- return nil , vterrors .Wrap (err , "unexpected error generating diff" )
653- }
654- dr .ExtraRowsSourceDiffs = append (dr .ExtraRowsSourceDiffs , diffRow )
655- count , err := sourceExecutor .drain (ctx )
656- if err != nil {
657- return nil , err
669+ // No more rows from the target; drain the remaining source rows,
670+ // saving a sample for each one (up to maxExtraRowsToCompare) so that
671+ // reconcileExtraRows can match them against any extra target rows.
672+ // As above, the drained rows are merged into the report only after
673+ // the full drain succeeds.
674+ drainedRows := int64 (0 )
675+ var drainedDiffs []* RowDiff
676+ for sourceRow != nil {
677+ if dr .ExtraRowsSource + drainedRows < maxExtraRowsToCompare {
678+ diffRow , err := td .genRowDiff (td .tablePlan .sourceQuery , sourceRow , reportOpts )
679+ if err != nil {
680+ return nil , vterrors .Wrap (err , "unexpected error generating diff" )
681+ }
682+ drainedDiffs = append (drainedDiffs , diffRow )
683+ }
684+ drainedRows ++
685+ sourceRow , err = sourceExecutor .next ()
686+ if err != nil {
687+ return nil , err
688+ }
658689 }
659- dr .ExtraRowsSource += 1 + count
660- dr .ProcessedRows += 1 + count
690+ dr .ExtraRowsSource += drainedRows
691+ dr .ProcessedRows += drainedRows
692+ dr .ExtraRowsSourceDiffs = append (dr .ExtraRowsSourceDiffs , drainedDiffs ... )
661693 return dr , nil
662694 }
663695
0 commit comments