@@ -2185,9 +2185,7 @@ func (w *worker) rollbackLikeDropPartition(jobCtx *jobContext, job *model.Job) (
2185
2185
2186
2186
var dropIndices []* model.IndexInfo
2187
2187
for _ , indexInfo := range tblInfo .Indices {
2188
- if indexInfo .Unique &&
2189
- indexInfo .State == model .StateDeleteReorganization &&
2190
- tblInfo .Partition .DDLState == model .StateDeleteReorganization {
2188
+ if indexInfo .State == model .StateWriteOnly {
2191
2189
dropIndices = append (dropIndices , indexInfo )
2192
2190
}
2193
2191
}
@@ -3043,9 +3041,6 @@ func (w *worker) onExchangeTablePartition(jobCtx *jobContext, job *model.Job) (v
3043
3041
}
3044
3042
3045
3043
func getNewGlobal (partInfo * model.PartitionInfo , idx * model.IndexInfo ) bool {
3046
- if len (partInfo .DDLUpdateIndexes ) == 0 {
3047
- return idx .Global
3048
- }
3049
3044
for _ , newIdx := range partInfo .DDLUpdateIndexes {
3050
3045
if strings .EqualFold (idx .Name .L , newIdx .IndexName ) {
3051
3046
return newIdx .Global
@@ -3151,6 +3146,9 @@ func getReorgPartitionInfo(t *meta.Mutator, job *model.Job, args *model.TablePar
3151
3146
//
3152
3147
// Everything now looks as it should, no memory of old partitions/indexes,
3153
3148
// and no more double writing, since the previous state is only reading the new partitions/indexes.
3149
+ //
3150
+ // Note: Special handling is also required in tables.newPartitionedTable(),
3151
+ // to get per partition indexes in the right state.
3154
3152
func (w * worker ) onReorganizePartition (jobCtx * jobContext , job * model.Job ) (ver int64 , _ error ) {
3155
3153
args , err := model .GetTablePartitionArgs (job )
3156
3154
if err != nil {
@@ -3262,39 +3260,33 @@ func (w *worker) onReorganizePartition(jobCtx *jobContext, job *model.Job) (ver
3262
3260
if err != nil {
3263
3261
return ver , errors .Trace (err )
3264
3262
}
3265
- if ! inAllPartitionColumns {
3266
- // Currently only support Explicit Global indexes.
3267
- if ! newGlobal {
3268
- job .State = model .JobStateCancelled
3269
- return ver , dbterror .ErrGlobalIndexNotExplicitlySet .GenWithStackByArgs (index .Name .O )
3270
- }
3271
- // Duplicate the unique indexes with new index ids.
3272
- // If previously was Global or will be Global:
3273
- // it must be recreated with new index ID
3274
- // TODO: Could we allow that session in StateWriteReorganization, when StateDeleteReorganization
3275
- // has started, may not find changes through the global index that sessions in StateDeleteReorganization made?
3276
- // If so, then we could avoid copying the full Global Index if it has not changed from LOCAL!
3277
- // It might be possible to use the new, not yet public partitions to access those rows?!
3278
- // Just that it would not work with explicit partition select SELECT FROM t PARTITION (p,...)
3279
- newIndex := index .Clone ()
3280
- newIndex .State = model .StateDeleteOnly
3281
- newIndex .ID = AllocateIndexID (tblInfo )
3282
- newIndex .Global = true
3283
- tblInfo .Indices = append (tblInfo .Indices , newIndex )
3284
- } else {
3285
- if newGlobal {
3286
- // TODO: For the future loosen this restriction and allow global indexes for unique keys also including all partitioning columns
3287
- return ver , dbterror .ErrGeneralUnsupportedDDL .GenWithStackByArgs (fmt .Sprintf ("PARTITION BY, index '%v' is unique and contains all partitioning columns, but has Global Index set" , index .Name .O ))
3288
- }
3289
- if index .Global {
3290
- // Index was previously Global, now it needs to be duplicated and become a local index.
3291
- newIndex := index .Clone ()
3292
- newIndex .State = model .StateDeleteOnly
3293
- newIndex .ID = AllocateIndexID (tblInfo )
3294
- newIndex .Global = false
3295
- tblInfo .Indices = append (tblInfo .Indices , newIndex )
3296
- }
3263
+ // Currently only support Explicit Global indexes.
3264
+ if ! inAllPartitionColumns && ! newGlobal {
3265
+ job .State = model .JobStateCancelled
3266
+ return ver , dbterror .ErrGlobalIndexNotExplicitlySet .GenWithStackByArgs (index .Name .O )
3267
+ }
3268
+ if ! index .Global && ! newGlobal {
3269
+ // still local index, no need to duplicate index.
3270
+ continue
3297
3271
}
3272
+ if tblInfo .Partition .DDLChangedIndex == nil {
3273
+ tblInfo .Partition .DDLChangedIndex = make (map [int64 ]bool )
3274
+ }
3275
+ // Duplicate the unique indexes with new index ids.
3276
+ // If previously was Global or will be Global:
3277
+ // it must be recreated with new index ID
3278
+ // TODO: Could we allow that session in StateWriteReorganization, when StateDeleteReorganization
3279
+ // has started, may not find changes through the global index that sessions in StateDeleteReorganization made?
3280
+ // If so, then we could avoid copying the full Global Index if it has not changed from LOCAL!
3281
+ // It might be possible to use the new, not yet public partitions to access those rows?!
3282
+ // Just that it would not work with explicit partition select SELECT FROM t PARTITION (p,...)
3283
+ newIndex := index .Clone ()
3284
+ newIndex .State = model .StateDeleteOnly
3285
+ newIndex .ID = AllocateIndexID (tblInfo )
3286
+ tblInfo .Partition .DDLChangedIndex [index .ID ] = false
3287
+ tblInfo .Partition .DDLChangedIndex [newIndex .ID ] = true
3288
+ newIndex .Global = newGlobal
3289
+ tblInfo .Indices = append (tblInfo .Indices , newIndex )
3298
3290
}
3299
3291
failpoint .Inject ("reorgPartCancel1" , func (val failpoint.Value ) {
3300
3292
if val .(bool ) {
@@ -3487,26 +3479,18 @@ func (w *worker) onReorganizePartition(jobCtx *jobContext, job *model.Job) (ver
3487
3479
if ! index .Unique {
3488
3480
continue
3489
3481
}
3490
- switch index .State {
3491
- case model .StateWriteReorganization :
3482
+ isNew , ok := tblInfo .Partition .DDLChangedIndex [index .ID ]
3483
+ if ! ok {
3484
+ continue
3485
+ }
3486
+ if isNew {
3492
3487
// Newly created index, replacing old unique/global index
3493
3488
index .State = model .StatePublic
3494
- case model .StatePublic :
3495
- if index .Global {
3496
- // Mark the old global index as non-readable, and to be dropped
3497
- index .State = model .StateDeleteReorganization
3498
- } else {
3499
- inAllPartitionColumns , err := checkPartitionKeysConstraint (partInfo , index .Columns , tblInfo )
3500
- if err != nil {
3501
- return rollbackReorganizePartitionWithErr (jobCtx , job , err )
3502
- }
3503
- if ! inAllPartitionColumns {
3504
- // Mark the old unique index as non-readable, and to be dropped,
3505
- // since it is replaced by a global index
3506
- index .State = model .StateDeleteReorganization
3507
- }
3508
- }
3489
+ continue
3509
3490
}
3491
+ // Old index, should not be visible any longer,
3492
+ // but needs to be kept up-to-date in case rollback happens.
3493
+ index .State = model .StateWriteOnly
3510
3494
}
3511
3495
firstPartIdx , lastPartIdx , idMap , err2 := getReplacedPartitionIDs (partNames , tblInfo .Partition )
3512
3496
if err2 != nil {
@@ -3563,14 +3547,18 @@ func (w *worker) onReorganizePartition(jobCtx *jobContext, job *model.Job) (ver
3563
3547
3564
3548
var dropIndices []* model.IndexInfo
3565
3549
for _ , indexInfo := range tblInfo .Indices {
3566
- if indexInfo .Unique && indexInfo .State == model .StateDeleteReorganization {
3550
+ if indexInfo .Unique && indexInfo .State == model .StateWriteOnly {
3567
3551
// Drop the old unique (possible global) index, see onDropIndex
3568
3552
indexInfo .State = model .StateNone
3569
3553
DropIndexColumnFlag (tblInfo , indexInfo )
3570
3554
RemoveDependentHiddenColumns (tblInfo , indexInfo )
3571
3555
dropIndices = append (dropIndices , indexInfo )
3572
3556
}
3573
3557
}
3558
+ // TODO: verify that the indexes are dropped,
3559
+ // and that StateDeleteOnly+StateDeleteReorganization is not needed.
3560
+ // local indexes is not an issue, since they will be gone with the dropped
3561
+ // partitions, but replaced global indexes should be checked!
3574
3562
for _ , indexInfo := range dropIndices {
3575
3563
removeIndexInfo (tblInfo , indexInfo )
3576
3564
}
@@ -3632,6 +3620,9 @@ func (w *worker) onReorganizePartition(jobCtx *jobContext, job *model.Job) (ver
3632
3620
failpoint .Return (ver , errors .New ("Injected error by reorgPartFail5" ))
3633
3621
}
3634
3622
})
3623
+ failpoint .Inject ("updateVersionAndTableInfoErrInStateDeleteReorganization" , func () {
3624
+ failpoint .Return (ver , errors .New ("Injected error in StateDeleteReorganization" ))
3625
+ })
3635
3626
args .OldPhysicalTblIDs = physicalTableIDs
3636
3627
args .NewPartitionIDs = newIDs
3637
3628
ver , err = updateVersionAndTableInfo (jobCtx , job , tblInfo , true )
0 commit comments