Skip to content

opgen: make Column transitioning to public non-revertible#88489

Merged
craig[bot] merged 1 commit intocockroachdb:masterfrom
Xiang-Gu:fix_add_column_unqiue_index_still_not_ready_when_primary_index_swap
Oct 4, 2022
Merged

opgen: make Column transitioning to public non-revertible#88489
craig[bot] merged 1 commit intocockroachdb:masterfrom
Xiang-Gu:fix_add_column_unqiue_index_still_not_ready_when_primary_index_swap

Conversation

@Xiang-Gu
Copy link
Copy Markdown
Contributor

@Xiang-Gu Xiang-Gu commented Sep 22, 2022

Delayed the transitioning of the Column element into PUBLIC to
the PostCommitNonRevertible phase. This helps with stmt like
ALTER TABLE t ADD COLUMN j INT DEFAULT 30 UNIQUE where we will
first do the pirmary index swap, then backfill the new unique secondary
index, and finally turn the column and the new unique secondary index
into public at the same stage. Previously, the column would incorrectly
turn into public before the new unique secondary index even begins
backfilling.

Fixes #82953

Release note: None

@cockroach-teamcity
Copy link
Copy Markdown
Member

This change is Reviewable

@Xiang-Gu Xiang-Gu force-pushed the fix_add_column_unqiue_index_still_not_ready_when_primary_index_swap branch 2 times, most recently from ded1737 to 9c2b5fe Compare October 3, 2022 15:58
@Xiang-Gu
Copy link
Copy Markdown
Contributor Author

Xiang-Gu commented Oct 3, 2022

I didn't fully understand the fix in the previous iteration and came up with a dep rule that didn't actually solve the problem. That dep rule delays the primary index swap and column turning public to happen in the same stage as the new unique secondary index turning public. This is not right because we would never be able to backfill the new unique secondary index to begin with, because that new column is not present in the (old) primary index. The reason we had such a requirement is definitely not obvious: it's related to an assumption that the optimizer holds deeply in the code and it's not easy to change any time soon. See this slack discussion for more details with an example included there.

The alternative @ajwerner suggested is to mark the transition of the column element into public non-revertible. What this entails is that we would respect the requirement by swapping the primary index first while keeping the column in WRITE_ONLY. We then backfill the new unique secondary index. Finally, in the non-revertible phase, we transition the column and the new unique secondary index into public in the same stage.

@postamar
Copy link
Copy Markdown

postamar commented Oct 3, 2022

Whatever it takes. Regardless of this particular issue, I believe that making the column public a non-revertible op makes sense anyway. Go for it!

@Xiang-Gu
Copy link
Copy Markdown
Contributor Author

Xiang-Gu commented Oct 3, 2022

The only failed test in CI is marked by TeamCity as "flaky", so I think it's RFAL!

@Xiang-Gu Xiang-Gu marked this pull request as ready for review October 3, 2022 17:52
@Xiang-Gu Xiang-Gu requested a review from a team October 3, 2022 17:52
@Xiang-Gu Xiang-Gu changed the title rule: changed two dep rules opgen: make Column transitioning to public non-revertible Oct 3, 2022
Copy link
Copy Markdown

@postamar postamar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nicely done. LGTM conditional on cosmetic changes.

// The new primary index should reach VALIDATED, a ready state to be used as
// source to backfill the new secondary index, before the secondary index becomes existent.
registerDepRule(
"primary index with new columns should exist before secondary indexes",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an oversight on my part when I moved these rule definitions about, I think, but I just noticed that "new columns" should not be mentioned at all in this rule name. This rule can come into play regardless of columns. Instead, it might be worth mentioning why this rule is required for ADD COLUMN UNIQUE in the commentary above.

statusesToPublicOrTransient(from, scpb.Status_VALIDATED, to, scpb.Status_DELETE_ONLY),
}
})
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These rules should remain where they were in the dep_add_index.go file.

Copy link
Copy Markdown
Contributor

@ajwerner ajwerner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there something that enforces that the primary index moves to public before any indexes involving a new column moves to DELETE_ONLY? It seems like maybe we're under-constrained and getting lucky.

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @postamar and @Xiang-Gu)

Copy link
Copy Markdown
Contributor Author

@Xiang-Gu Xiang-Gu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ajwerner Marius had these two rules:

// We want to say that all columns which are part of a secondary index need
// to be in a primary index which is validated
// To do that, we want to find a secondary index which has a source which
// is a primary index which is itself new.
func init() {
registerDepRule(
"primary index with new columns should exist before secondary indexes",
scgraph.Precedence,
"primary-index", "secondary-index",
func(from, to nodeVars) rel.Clauses {
return rel.Clauses{
from.Type((*scpb.PrimaryIndex)(nil)),
to.Type((*scpb.SecondaryIndex)(nil)),
joinOnDescID(from, to, "table-id"),
joinOn(
from, screl.IndexID,
to, screl.SourceIndexID,
"primary-index-id",
),
statusesToPublicOrTransient(from, scpb.Status_PUBLIC, to, scpb.Status_BACKFILL_ONLY),
}
})
registerDepRule(
"primary index with new columns should exist before temp indexes",
scgraph.Precedence,
"primary-index", "temp-index",
func(from, to nodeVars) rel.Clauses {
return rel.Clauses{
from.Type((*scpb.PrimaryIndex)(nil)),
to.Type((*scpb.TemporaryIndex)(nil)),
joinOnDescID(from, to, "table-id"),
joinOn(
from, screl.IndexID,
to, screl.SourceIndexID,
"primary-index-id",
),
statusesToPublicOrTransient(from, scpb.Status_PUBLIC, to, scpb.Status_DELETE_ONLY),
}
})
}

that made sure if we are adding both primary index and a secondary index, and the source index of the secondary index is the primary index, as in the case for ADD COLUMN UNIQUE, then we make sure we the primary index transitioned to PUBLIC before the secondary index transitioned to BACKFILL_ONLY.

Does this answer your questions?

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @postamar)


pkg/sql/schemachanger/scplan/internal/rules/dep_add_column.go line 118 at r2 (raw file):

Previously, postamar (Marius Posta) wrote…

This is an oversight on my part when I moved these rule definitions about, I think, but I just noticed that "new columns" should not be mentioned at all in this rule name. This rule can come into play regardless of columns. Instead, it might be worth mentioning why this rule is required for ADD COLUMN UNIQUE in the commentary above.

I guess I am a bit confused about their original comments here

// We want to say that all columns which are part of a secondary index need
// to be in a primary index which is validated
// To do that, we want to find a secondary index which has a source which
// is a primary index which is itself new.

Are they stale? Do you want me to keep the updated comments but just move those two rules back to dep_add_index.go?


pkg/sql/schemachanger/scplan/internal/rules/dep_add_column.go line 154 at r2 (raw file):

Previously, postamar (Marius Posta) wrote…

These rules should remain where they were in the dep_add_index.go file.

ack above.

Copy link
Copy Markdown
Contributor

@ajwerner ajwerner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it does, no. Didn't you delete that rule in this PR and change it to be about the primary index moving into validated prior to the temp index moving into DELETE_ONLY?

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @postamar)

Copy link
Copy Markdown
Contributor Author

@Xiang-Gu Xiang-Gu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, right. I realized that and since we are not adding any dep rules anymore, I reverted the changes on the existing rules. But I haven't pushed the code yet.

With this existing rule, do you think we have constrained it properly?

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @postamar)

@Xiang-Gu Xiang-Gu force-pushed the fix_add_column_unqiue_index_still_not_ready_when_primary_index_swap branch from 9c2b5fe to 0317cfc Compare October 3, 2022 21:48
Copy link
Copy Markdown
Contributor Author

@Xiang-Gu Xiang-Gu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just pushed the reverts; now this PR is truly a one-line changer revertible(false); under opgen_column.go

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @postamar)

Copy link
Copy Markdown
Contributor

@ajwerner ajwerner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this looks right to me from the tests we have. Can you add an end-to-end test with a default value and a unique constraint?

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @postamar)

This PR delays the transitioning of the Column element into PUBLIC to
the PostCommitNonRevertible phase. This helps with stmt like
`ALTER TABLE t ADD COLUMN j INT DEFAULT 30 UNIQUE` where we will
first do the pirmary index swap, then backfill the new unique secondary
index, and finally turn the column and the new unique secondary index
into public at the same stage. Previously, the column would incorrectly
turn into public before the new unique secondary index even begins
backfilling, as detailed in cockroachdb#82953.

Release note: None
@Xiang-Gu Xiang-Gu force-pushed the fix_add_column_unqiue_index_still_not_ready_when_primary_index_swap branch from 0317cfc to 32b766a Compare October 4, 2022 15:57
Copy link
Copy Markdown
Contributor Author

@Xiang-Gu Xiang-Gu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ajwerner
I added an end-to-end test for ADD COLUMN DEFAULT UNIQUE and generated the expected output.

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @postamar)


pkg/sql/schemachanger/scplan/internal/rules/dep_add_column.go line 118 at r2 (raw file):

Previously, Xiang-Gu (Xiang Gu) wrote…

I guess I am a bit confused about their original comments here

// We want to say that all columns which are part of a secondary index need
// to be in a primary index which is validated
// To do that, we want to find a secondary index which has a source which
// is a primary index which is itself new.

Are they stale? Do you want me to keep the updated comments but just move those two rules back to dep_add_index.go?

I reverted this change -- it turns out we don't and shouldn't need to modify the existing rules; they are needed to constrain the graph such that the new unique secondary index (as well its temp index) didn't move out of ABSENT until the new primary index is PUBLIC.

Copy link
Copy Markdown
Contributor

@ajwerner ajwerner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

Reviewable status: :shipit: complete! 1 of 0 LGTMs obtained (waiting on @postamar)

@Xiang-Gu
Copy link
Copy Markdown
Contributor Author

Xiang-Gu commented Oct 4, 2022

TFTR!

bors r+

@craig
Copy link
Copy Markdown
Contributor

craig bot commented Oct 4, 2022

Build succeeded:

@Xiang-Gu
Copy link
Copy Markdown
Contributor Author

Xiang-Gu commented Oct 5, 2022

blathers backport 22.2 22.2.0

@blathers-crl
Copy link
Copy Markdown

blathers-crl bot commented Oct 5, 2022

Encountered an error creating backports. Some common things that can go wrong:

  1. The backport branch might have already existed.
  2. There was a merge conflict.
  3. The backport branch contained merge commits.

You might need to create your backport manually using the backport tool.


error creating merge commit from 32b766a to blathers/backport-release-22.2-88489: POST https://api.github.com/repos/cockroachdb/cockroach/merges: 409 Merge conflict []

you may need to manually resolve merge conflicts with the backport tool.

Backport to branch 22.2 failed. See errors above.


error creating merge commit from 32b766a to blathers/backport-release-22.2.0-88489: POST https://api.github.com/repos/cockroachdb/cockroach/merges: 409 Merge conflict []

you may need to manually resolve merge conflicts with the backport tool.

Backport to branch 22.2.0 failed. See errors above.


🦉 Hoot! I am a Blathers, a bot for CockroachDB. My owner is otan.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sql/schemachanger: column prematurely turns to PUBLIC in ADD COLUMN ... UNIQUE

4 participants