forked from cockroachdb/cockroach
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
upgrades: Added an cluster upgrade from v22.1 to v22.2
This upgrade attempts to update invalid column IDs in sequence back references, if any, on a best-effort basis. The context of the need for such an upgrade can be found in cockroachdb#82576. The summary there is bugs in prior versions might cause sequence descriptor corruption where their back references might contain a column ID 0. We ought to figure out what the actual column ID is and update such invalid column IDs.
- Loading branch information
Showing
8 changed files
with
170 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
141 changes: 141 additions & 0 deletions
141
pkg/upgrade/upgrades/update_invalid_column_ids_in_sequence_back_references.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
// Copyright 2022 The Cockroach Authors. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
|
||
package upgrades | ||
|
||
import ( | ||
"context" | ||
"reflect" | ||
"sort" | ||
|
||
"github.com/cockroachdb/cockroach/pkg/clusterversion" | ||
"github.com/cockroachdb/cockroach/pkg/jobs" | ||
"github.com/cockroachdb/cockroach/pkg/kv" | ||
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" | ||
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descs" | ||
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree" | ||
"github.com/cockroachdb/cockroach/pkg/sql/sqlutil" | ||
"github.com/cockroachdb/cockroach/pkg/upgrade" | ||
"github.com/cockroachdb/cockroach/pkg/util/log" | ||
"github.com/cockroachdb/errors" | ||
) | ||
|
||
func updateInvalidColumnIDsInSequenceBackReferences( | ||
ctx context.Context, _ clusterversion.ClusterVersion, d upgrade.TenantDeps, _ *jobs.Job, | ||
) error { | ||
// Scan all sequences and repair those with 0-valued column IDs in their back references, | ||
// one transaction for each repair. | ||
var lastSeqID descpb.ID | ||
|
||
for { | ||
var currSeqID descpb.ID | ||
var done bool | ||
if err := d.CollectionFactory.TxnWithExecutor(ctx, d.DB, d.SessionData, func( | ||
ctx context.Context, txn *kv.Txn, descriptors *descs.Collection, ie sqlutil.InternalExecutor, | ||
) (err error) { | ||
currSeqID = lastSeqID | ||
for { | ||
done, currSeqID, err = findNextTableToUpgrade(ctx, ie, currSeqID, | ||
func(table *descpb.TableDescriptor) bool { | ||
return table.IsSequence() | ||
}) | ||
if err != nil || done { | ||
return err | ||
} | ||
|
||
// Sequence `nextIdToUpgrade` might contain back reference with invalid column IDs. If so, we need to | ||
// update them with valid column IDs. | ||
hasUpgrade, err := maybeUpdateInvalidColumnIdsInSequenceBackReferences(ctx, txn, currSeqID, descriptors) | ||
if err != nil { | ||
return err | ||
} | ||
if hasUpgrade { | ||
return nil | ||
} | ||
} | ||
}); err != nil { | ||
return err | ||
} | ||
|
||
// Break out of the loop if we upgraded all sequences. | ||
if done { | ||
break | ||
} | ||
lastSeqID = currSeqID | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// maybeUpdateInvalidColumnIdsInSequenceBackReferences looks at sequence, identified | ||
// by `idToUpgrade`, and upgrade invalid column IDs in its back references, if any. | ||
// | ||
// The upgrade works by reconstructing the referenced column IDs in each back reference | ||
// in the sequence's `DependedOnBy` field. Reconstruction is possible with the help of | ||
// the `UsesSequenceIDs` field of each column in the referencing table. | ||
// | ||
// A canonical example to create a corrupt sequence descriptor with invalid column IDs is | ||
// to run the following in v21.1: | ||
// `CREATE SEQUENCE s; CREATE TABLE t (i INT PRIMARY KEY);` | ||
// followed by | ||
// `ALTER TABLE t ADD COLUMN j INT DEFAULT nextval('s'), ADD COLUMN k INT DEFAULT nextval('s')` | ||
// which erroneously added the back reference in sequence `s` before allocating a column ID | ||
// to the newly added column, causing the reference in `s.DependedOnBy` to be | ||
// `ref.ColumnIDs = [0, 0]` while it should instead be `ref.ColumnIDs = [2, 3]`. | ||
// This upgrade logic will look at the `UsesSequenceIds` field of each column (`i`, `j`, and `k`) | ||
// in `t`. In this case, exactly two columns (`j` and `k`) will have `UsesSequenceIds` that | ||
// contains id of `s`. We thus reconstruct and update `ref.ColumnIDs` to be `[2, 3]`. | ||
func maybeUpdateInvalidColumnIdsInSequenceBackReferences( | ||
ctx context.Context, txn *kv.Txn, idToUpgrade descpb.ID, descriptors *descs.Collection, | ||
) (hasUpgraded bool, err error) { | ||
// Get the sequence descriptor that we are going to upgrade. | ||
seqDesc, err := descriptors.GetMutableTableByID(ctx, txn, idToUpgrade, tree.ObjectLookupFlagsWithRequired()) | ||
if err != nil { | ||
return false, err | ||
} | ||
if !seqDesc.IsSequence() { | ||
return false, errors.AssertionFailedf("input id to upgrade %v is is not a sequence", idToUpgrade) | ||
} | ||
|
||
for i, ref := range seqDesc.DependedOnBy { | ||
// Re-construct the expected column IDs in `ref` and update | ||
// `ref.ColumnIDs` if the actual value is not equal to the | ||
// expected value. | ||
expectedColumnIDsInRef := make([]descpb.ColumnID, 0) | ||
tableDesc, err := descriptors.GetMutableTableByID(ctx, txn, ref.ID, tree.ObjectLookupFlagsWithRequired()) | ||
if err != nil { | ||
return false, err | ||
} | ||
for _, col := range tableDesc.GetColumns() { | ||
if descpb.IDs(col.UsesSequenceIds).Contains(seqDesc.ID) { | ||
expectedColumnIDsInRef = append(expectedColumnIDsInRef, col.ID) | ||
} | ||
} | ||
sort.Slice(expectedColumnIDsInRef, func(i, j int) bool { | ||
return expectedColumnIDsInRef[i] < expectedColumnIDsInRef[j] | ||
}) | ||
|
||
if !reflect.DeepEqual(ref.ColumnIDs, expectedColumnIDsInRef) { | ||
seqDesc.DependedOnBy[i].ColumnIDs = expectedColumnIDsInRef | ||
hasUpgraded = true | ||
} | ||
} | ||
|
||
if hasUpgraded { | ||
// Write the updated sequence descriptor to storage. | ||
log.Infof(ctx, "updated invalid column IDs in back references in sequence %v (%v)", | ||
seqDesc.Name, idToUpgrade) | ||
if err = descriptors.WriteDesc(ctx, false, seqDesc, txn); err != nil { | ||
return false, err | ||
} | ||
} | ||
|
||
return hasUpgraded, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters