-
Notifications
You must be signed in to change notification settings - Fork 3.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sql/schemachanger: add back TXN_DROPPED, stop using OFFLINE #86639
sql/schemachanger: add back TXN_DROPPED, stop using OFFLINE #86639
Conversation
c3c22c6
to
5e13723
Compare
This turns out to be insufficient; we need to make it such that the bulk of the work in the drop cases does happen during pre-commit. Otherwise, we're stuck with incompatibilities. |
5e13723
to
1f1ee74
Compare
f3e316b
to
ab3df2b
Compare
I fixed a few build errors, rebase on Master, and ran CI now reports test failures; we will need to look into them next. |
descriptor.typeFilter(IsDescriptor), | ||
descriptor.joinTarget(), | ||
joinOnDescIDUntyped(descriptor.el, element, "id"), | ||
descriptor.targetStatus(scpb.ToAbsent), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this line be descriptor.targetStatus(scpb.ToPublic)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we want this rule to unify if we are dropping the descriptor. The NotJoin
implies negation where it is used if everything inside the rule unifies.
from.typeFilter(IsDescriptor), | ||
from.el.AttrEqVar(screl.DescID, "_"), | ||
from.el.AttrEqVar(rel.Self, to.el), | ||
to.el.AttrEqVar(rel.Self, to.el), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this line always true and hence redundant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, removed
registerDepRule( | ||
"descriptor txn_drop before descriptor drop", | ||
scgraph.PreviousStagePrecedence, | ||
"descriptor", "dependent", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this rule is about making sure one descriptor reached TXN_DROPPED
before reaching DROPPED
in a previous stage, then we probably should change the name of the second variable dependent
to, maybe, descriptor_self
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, fixed
type statusFunc = func( | ||
from nodeVars, fromStatus scpb.Status, to nodeVars, toStatus scpb.Status, | ||
) rel.Clause | ||
addRules := func(c depElement, targetStatus scpb.TargetStatus, sf statusFunc) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems sf statusFunc
is not used. Did I miss something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, you're right. Removed.
// PreviousTransactionPrecedence is like PreviousStagePrecedence but does | ||
// not allow the transition to occur if the current phase is not PostCommit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you be elobarate a bit more on the comment? Does it meanfrom
must be reached before to
in a previous stage, and both stages must be in PostCommit phase? If so, what do you think of the name PreviousStageInPostCommitPrecendence
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It means that from
must be reached before to
in a previous stage and if from
was reached in StatementPhase
than to
cannot be reached in PreCommitPhase
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm open to both better naming and a better comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does not allow the transition to occur unless the current phase is at least PostCommitPhase, because StatementPhase and PreCommitPhase are special in that they take place in the same transaction
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
ab3df2b
to
ea5ba71
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking a look and fixing the issues. The validation things are interesting. I'll get to the bottom of them one way or another. I think I addressed the basic comments, but did it on the old version of the branch. I'll find and add back your changes.
// PreviousTransactionPrecedence is like PreviousStagePrecedence but does | ||
// not allow the transition to occur if the current phase is not PostCommit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It means that from
must be reached before to
in a previous stage and if from
was reached in StatementPhase
than to
cannot be reached in PreCommitPhase
.
// PreviousTransactionPrecedence is like PreviousStagePrecedence but does | ||
// not allow the transition to occur if the current phase is not PostCommit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm open to both better naming and a better comment.
type statusFunc = func( | ||
from nodeVars, fromStatus scpb.Status, to nodeVars, toStatus scpb.Status, | ||
) rel.Clause | ||
addRules := func(c depElement, targetStatus scpb.TargetStatus, sf statusFunc) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, you're right. Removed.
registerDepRule( | ||
"descriptor txn_drop before descriptor drop", | ||
scgraph.PreviousStagePrecedence, | ||
"descriptor", "dependent", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, fixed
from.typeFilter(IsDescriptor), | ||
from.el.AttrEqVar(screl.DescID, "_"), | ||
from.el.AttrEqVar(rel.Self, to.el), | ||
to.el.AttrEqVar(rel.Self, to.el), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, removed
descriptor.typeFilter(IsDescriptor), | ||
descriptor.joinTarget(), | ||
joinOnDescIDUntyped(descriptor.el, element, "id"), | ||
descriptor.targetStatus(scpb.ToAbsent), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we want this rule to unify if we are dropping the descriptor. The NotJoin
implies negation where it is used if everything inside the rule unifies.
8763145
to
cff1905
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is coming along nicely!
@@ -560,9 +560,18 @@ func (s *TestState) MustReadDescriptor(ctx context.Context, id descpb.ID) catalo | |||
return desc | |||
} | |||
|
|||
// AddSyntheticDescriptor is part of the scexec.Catalog interface. | |||
func (s *TestState) AddSyntheticDescriptor(desc catalog.MutableDescriptor) { | |||
s.LogSideEffectf("added synthetic descriptor: %v", desc) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we instead print the yaml diff between the synthetic descriptor and the existing immutable descriptor if it exists?
@@ -117,4 +117,6 @@ type MutationVisitorStateUpdater interface { | |||
|
|||
// RefreshStats refresh stats for a given descriptor. | |||
RefreshStats(id descpb.ID) | |||
MarkDescriptorSynthetic(id descpb.ID) | |||
// MarkDescriptorSynthetic(id descpb.ID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
detritus
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -322,7 +322,7 @@ func (sb stageBuilder) isOutgoingOpEdgeAllowed(e *scgraph.OpEdge) bool { | |||
if e.Type() != sb.opType { | |||
return false | |||
} | |||
if !e.IsPhaseSatisfied(sb.bs.phase) { | |||
if !e.IsPhaseSatisfied(sb.bs.phase) && !sb.bc.g.IsNoOp(e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. By the way, you probably should remove hasOpEdgeWithOps
and the logic around it in this PR. Search for // TODO(postamar): uphold the 2-version invariant using dep rules instead.
func makeRandomVars(n int) (ret []Var) { | ||
ret = make([]Var, n) | ||
for i := range ret { | ||
ret[i] = Var(hex.EncodeToString(uuid.MakeV4().GetBytes())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to hurt legibility when debugging. Can't we instead use a reserved prefix followed by a counter? You probably can assert that this reserved prefix isn't used in vars outside of rel.
// if we have a not-join, then we need to find the slots for the inputs | ||
// and we have to build the sub-query, which is a whole new query, and | ||
// we have to then figure out its depth. In general, its depth should be | ||
// the current join depth, so the current |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
incomplete comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved into processNotJoin
|
||
} | ||
|
||
// notJoinOnNodeWithStatusIn is a cache to memoize getNotJoinOnNodeWithStatusIn. a not-join rule which will |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
incomplete comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the tail
// IsPhaseSatisfied returns true iff the operations can run in the given phase. | ||
func (oe *OpEdge) IsPhaseSatisfied(phase scop.Phase) bool { | ||
return phase >= oe.minPhase | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good riddance.
@@ -361,7 +358,7 @@ func (sb stageBuilder) nextTargetState(t currentTargetState) currentTargetState | |||
} else { | |||
next.hasOpEdgeWithOps = true | |||
} | |||
} | |||
}*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just get rid of this, as suggested in a previous comment, along with hasOpEdgeWithOps
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
if sb.isUnmetInboundDep(de) { | ||
ret = true | ||
ret = sb.isUnmetInboundDep(de) | ||
if ret { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: is this really more readable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, there was some other code in an earlier iteration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I combined it.
return !fromIsFulfilled || | ||
(sb.bs.phase <= scop.PreCommitPhase && | ||
// If it has been fulfilled implicitly because it's the initial | ||
// status, then it doesn't matter the current phase, let it go. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then the current phase doesn't matter
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My comments are just nits, so LGTM.
cff1905
to
a6c8876
Compare
We added the `OFFLINE` and performed write operations during drops to move the descriptor into that state in order to deal with the fact that synthetically dropped descriptors would not appear so in virtual tables. Fortunately, this shortcoming has been rectified. We now revive the TXN_DROPPED state. This proves to be important because the `OFFLINE` state is not backwards compatible, and the `TXN_DROPPED` state is. Ideally we'd find a way to move the descriptors straight to `DROPPED` in the pre-commit case for all the cases we today support, but doing that would require an overhaul of the dependency rules which,at this point in the cycle, feels risky. Fixes cockroachdb#86626 Release justification: Fixes a release-blocking backwards incompatibility. Release note: None
…reCommit We can schedule non-revertible operations into PreCommit so long as the next stage is PostCommitNonRevertible. Release justification: part of bug fix Release note: None
…dges Release note: None
This is just to avoid bugs later. Release justification: cleanup Release note: None
a6c8876
to
6a7477d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I took your changes and addressed the comments.
return !fromIsFulfilled || | ||
(sb.bs.phase <= scop.PreCommitPhase && | ||
// If it has been fulfilled implicitly because it's the initial | ||
// status, then it doesn't matter the current phase, let it go. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
if sb.isUnmetInboundDep(de) { | ||
ret = true | ||
ret = sb.isUnmetInboundDep(de) | ||
if ret { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, there was some other code in an earlier iteration.
if sb.isUnmetInboundDep(de) { | ||
ret = true | ||
ret = sb.isUnmetInboundDep(de) | ||
if ret { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I combined it.
@@ -361,7 +358,7 @@ func (sb stageBuilder) nextTargetState(t currentTargetState) currentTargetState | |||
} else { | |||
next.hasOpEdgeWithOps = true | |||
} | |||
} | |||
}*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
// PreviousTransactionPrecedence is like PreviousStagePrecedence but does | ||
// not allow the transition to occur if the current phase is not PostCommit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
} | ||
|
||
// notJoinOnNodeWithStatusIn is a cache to memoize getNotJoinOnNodeWithStatusIn. a not-join rule which will |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the tail
panic(err) | ||
} | ||
} | ||
_ = screl.ForEachElementType(func(el scpb.Element) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, deleted the new one.
// if we have a not-join, then we need to find the slots for the inputs | ||
// and we have to build the sub-query, which is a whole new query, and | ||
// we have to then figure out its depth. In general, its depth should be | ||
// the current join depth, so the current |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved into processNotJoin
@@ -117,4 +117,6 @@ type MutationVisitorStateUpdater interface { | |||
|
|||
// RefreshStats refresh stats for a given descriptor. | |||
RefreshStats(id descpb.ID) | |||
MarkDescriptorSynthetic(id descpb.ID) | |||
// MarkDescriptorSynthetic(id descpb.ID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
e67e63e
to
2ada0c2
Compare
CI is failing due to a compilation error: Let's 🚢 🇮🇹. My very minor concern about the var generator can wait another day. |
2ada0c2
to
1051bf0
Compare
This patch endows rel with the ability to define not-join rules which allow extra variables to be introduced inside the clauses. When a not-join rule is invoked, it leads to the outer query finding a contradiction if the rule fully unifies. Fixes cockroachdb#77148 Release justification: part of a broader bug-fix Release note: None
…ules Previously we had implicit rules in opgen which were used to enforce sequencing between transitions. This was brittle and made it hard to collapse certain edges. Now that we can represent a not-join, we can add the rules we want selectively, only when descriptors are not being dropped. Fixes cockroachdb#86691 Fixes cockroachdb#86626 Release justification: fixes a bug Release note: None
1051bf0
to
affdfee
Compare
TFTR! bors r=postamar |
Build succeeded: |
The first two commits enable synthetic descriptors to be used during transaction
execution to influence the virtual tables.
We added the
OFFLINE
and performed write operations during drops to move thedescriptor into that state in order to deal with the fact that synthetically
dropped descriptors would not appear so in virtual tables. Fortunately, this
shortcoming has been rectified. We now revive the TXN_DROPPED state. This
proves to be important because the
OFFLINE
state is not backwards compatible,and the
TXN_DROPPED
state is. Ideally we'd find a way to move the descriptorsstraight to
DROPPED
in the pre-commit case for all the cases we today support,but doing that would require an overhaul of the dependency rules which, at this
point in the cycle, feels risky.
Fixes #86626
Fixes #77148
Fixes #86691
Release justification: Fixes a release-blocking backwards incompatibility.
Release note: None