-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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,sqlbase,client: bootstrap TableDescriptor timestamps from MVCC #40793
sql,sqlbase,client: bootstrap TableDescriptor timestamps from MVCC #40793
Conversation
9fe1b55
to
170f106
Compare
There was some churn here because of a discovery: before 19.1 we did not set the The logic in I'm hopeful we can agree to still put in this change as it's a real customer pain point and I understand that this revealed some added risk. |
170f106
to
a7bdba9
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.
Reviewable status:
complete! 0 of 0 LGTMs obtained (waiting on @ajwerner, @andreimatei, and @lucy-zhang)
pkg/ccl/backupccl/restore.go, line 48 at r3 (raw file):
"github.com/cockroachdb/cockroach/pkg/util/tracing" "github.com/cockroachdb/errors" opentracing "github.com/opentracing/opentracing-go"
This got added again.
pkg/ccl/backupccl/restore.go, line 78 at r3 (raw file):
return nil, errors.Wrapf(err, "failed to read backup descriptor") } for _, d := range desc.Descriptors {
I think all this should actually go in readBackupDescriptor()
, which is ultimately what gets called whenever we read a backup descriptor (which happens in a few other places besides this one).
pkg/ccl/backupccl/restore.go, line 91 at r3 (raw file):
if t := d.GetTable(); t == nil { continue } else if t.Version == 1 && t.ModificationTime.IsEmpty() {
I had thought that we would never make a >=19.1 backup of a table descriptor without a ModificationTime
. Even in 19.2, a table descriptor must be read before it is written to the backup descriptor, at which point a timestamp would have been set if it hadn't been set already, right?
(Also, is it possible to just indiscriminately set the ModificationTime
to 1
whenever we restored a table? Is there any advantage to keeping the old timestamp?)
pkg/sql/sqlbase/structured.go, line 3305 at r3 (raw file):
func (desc *TableDescriptor) maybeSetTimeFromMVCCTimestamp(ts hlc.Timestamp) { // CreateAsOfTime is used for CREATE TABLE ... AS SELECT ... and was // introduced in v19.1. In general it is not critical to set and we definitely
Sorry I forgot about the CREATE TABLE AS
complications in my earlier review. I think this comment could be clearer about CreateAsOfTime
being set if and only if the table was created from CREATE TABLE AS
. (Though in practice I think it's harmless if the timestamp isn't set as long as the table isn't in the ADD
state anymore. We only use it as a transaction timestamp when filling in the table.)
Along those same lines, maybe there should be an assertion that if table.Adding() && table.IsAs()
, we either have the timestamp already set or have a value to set it to.
pkg/sql/sqlbase/structured.proto, line 826 at r3 (raw file):
// version of a table and is populated from the MVCC timestamp of the read // like ModificationTime. See Descriptor.Table(). // CreateAsOfSystemTime is used for CREATE TABLE ... AS SELECT ... and was
nit: CREATE TABLE ... AS ...
982c6eb
to
7df3d2f
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.
Reviewable status:
complete! 0 of 0 LGTMs obtained (waiting on @andreimatei and @lucy-zhang)
pkg/ccl/backupccl/restore.go, line 48 at r3 (raw file):
Previously, lucy-zhang (Lucy Zhang) wrote…
This got added again.
Done.
pkg/ccl/backupccl/restore.go, line 78 at r3 (raw file):
Previously, lucy-zhang (Lucy Zhang) wrote…
I think all this should actually go in
readBackupDescriptor()
, which is ultimately what gets called whenever we read a backup descriptor (which happens in a few other places besides this one).
Done.
pkg/ccl/backupccl/restore.go, line 91 at r3 (raw file):
I had thought that we would never make a >=19.1 backup of a table descriptor without a
ModificationTime
.
True but we need to support restoring from backups made from any version.
(Also, is it possible to just indiscriminately set the ModificationTime to 1 whenever we restored a table? Is there any advantage to keeping the old timestamp?)
Seems like it should be. The main value of the old timestamp as far as I can tell is that it will correspond to the MVCC time range of keys which contain that physical format. It's totally possible that I misunderstand how restoring a table interacts with MVCC but my expectation is that the restored keys will carry the same timestamp as when they were exported. If that's false then I feel way less strongly about preserving the ModificationTime.
pkg/sql/sqlbase/structured.go, line 3305 at r3 (raw file):
Previously, lucy-zhang (Lucy Zhang) wrote…
Sorry I forgot about the
CREATE TABLE AS
complications in my earlier review. I think this comment could be clearer aboutCreateAsOfTime
being set if and only if the table was created fromCREATE TABLE AS
. (Though in practice I think it's harmless if the timestamp isn't set as long as the table isn't in theADD
state anymore. We only use it as a transaction timestamp when filling in the table.)Along those same lines, maybe there should be an assertion that if
table.Adding() && table.IsAs()
, we either have the timestamp already set or have a value to set it to.
Done.
pkg/sql/sqlbase/structured.proto, line 826 at r3 (raw file):
Previously, lucy-zhang (Lucy Zhang) wrote…
nit:
CREATE TABLE ... AS ...
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.
Reviewable status:
complete! 1 of 0 LGTMs obtained (waiting on @ajwerner, @andreimatei, and @lucy-zhang)
pkg/ccl/backupccl/restore.go, line 80 at r6 (raw file):
backupDescs[i] = desc }
nit: spurious diff
pkg/ccl/backupccl/restore_old_versions_test.go, line 38 at r6 (raw file):
for _, dir := range dirs { require.True(t, dir.IsDir()) t.Run(dir.Name(), restoreOldVersionTest(dir.Name()))
nit: pass path.join(exportDirs, dir)
and localize exportDirs
and testdataBase
to this function.
pkg/ccl/backupccl/testdata/restore_old_versions/create.sql, line 1 at r6 (raw file):
-- The below SQL is used to create the data that is then exported with BACKUP
I'm really happy that you wrote these tests, but can you please also paste in here somewhere the exact commands to produce the ssts?
pkg/sql/sqlbase/structured.go, line 3318 at r6 (raw file):
desc.CreateAsOfTime = ts }
spurious diff
7df3d2f
to
c32024f
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.
TFTR!
Reviewable status:
complete! 0 of 0 LGTMs obtained (and 1 stale) (waiting on @andreimatei and @lucy-zhang)
pkg/ccl/backupccl/restore.go, line 80 at r6 (raw file):
Previously, andreimatei (Andrei Matei) wrote…
nit: spurious diff
Done.
pkg/ccl/backupccl/restore_old_versions_test.go, line 38 at r6 (raw file):
Previously, andreimatei (Andrei Matei) wrote…
nit: pass
path.join(exportDirs, dir)
and localizeexportDirs
andtestdataBase
to this function.
Done.
pkg/ccl/backupccl/testdata/restore_old_versions/create.sql, line 1 at r6 (raw file):
Previously, andreimatei (Andrei Matei) wrote…
I'm really happy that you wrote these tests, but can you please also paste in here somewhere the exact commands to produce the ssts?
Added it to the test comment.
pkg/sql/sqlbase/structured.go, line 3318 at r6 (raw file):
Previously, andreimatei (Andrei Matei) wrote…
spurious diff
I think I like this one.
cd97539
to
622a081
Compare
@lucy-zhang can I have your stamp on this before I bors it? |
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.
Reviewable status:
complete! 0 of 0 LGTMs obtained (and 1 stale) (waiting on @ajwerner, @andreimatei, and @lucy-zhang)
pkg/ccl/backupccl/restore.go, line 91 at r3 (raw file):
True but we need to support restoring from backups made from any version.
Yeah, agreed, I actually just misread the comment/code previously.
pkg/sql/sqlbase/structured.go, line 3323 at r7 (raw file):
if desc.Adding() && desc.IsAs() && desc.CreateAsOfTime.IsEmpty() { log.Fatalf(context.TODO(), "table descriptor for %q (%d.%d) is in the "+ "ADD state and was creates with CREATE TABLE ... AS but does not have a "+
created
Using the MVCC timestamp of the value for table descriptors has long been theorized as the right mechanism to eliminate the need for transactions which update a table descriptor version to observe their commit timestamp (see cockroachdb#17698 (comment)). The challenge was presumed to be the need to expose MVCC timestamps in our client library. It turns out we seem to do that already (how did nobody know that?!). This commit avoids using the CommitTimestamp by using the MVCC timestamp on the read path. In order to make this setting of the timestamp less of a footgun we add a `(*Descriptor).Table(hlc.Timestamp)` method which forces anybody who extracts a `TableDescriptor` from a `Descriptor` to pass in a timestamp which may be used to set `ModificationTime` and `CreateAsOfTime`. A linter in the following commit enforces this proper usage. The below SQL would always fail before this change and now passes: ``` CREATE TABLE foo ( k INT PRIMARY KEY ); BEGIN; DROP TABLE foo; <wait a while> COMMIT; ``` Similarly the TestImportData seems to pass under stressrace with a 5s `kv.closed_timestamp.target_duration`. Release justification: fixes a release blocker and known customer issue. References cockroachdb#37083. Release note: None
Callers should use sqlbase.Descriptor.Table() instead. Release justification: This is a linter for the first commit which is an approved change. Release note: None
… versions This PR ensures that the now logic to set the TableDescriptor timestamps from MVCC timestamps works in the face of table descriptors created in previous versions. There are two main hazards which this commit addresses: 1) Tables created before 19.1 will not carry a CreateAsOfTimestamp. This field is not important to set on these tables as they certainly were not relying on this value for a CTAS. 2) Ensure that TableDescriptors from a backup contain a non-zero ModificationTime. Before 19.1 we created Version 1 of tables with a zero ModificationTime. When restoring such a table we set its ModificationTime to hlc.Timestamp{WallTime: 1}. This prevents any invariants from being violated. This commit also adds a test to backupccl which restores a database from all previous major versions to ensure that the restore works properly. Release Justification: Fixes a bug in a PR which was approved for release and adds testing. Release note: None
622a081
to
05a000a
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.
TFTR!
bors r+
Reviewable status:
complete! 0 of 0 LGTMs obtained (and 1 stale) (waiting on @ajwerner, @andreimatei, and @lucy-zhang)
pkg/sql/sqlbase/structured.go, line 3323 at r7 (raw file):
Previously, lucy-zhang (Lucy Zhang) wrote…
created
Done.
40793: sql,sqlbase,client: bootstrap TableDescriptor timestamps from MVCC r=ajwerner a=ajwerner This PR adds back the changes in #40581 and deals with the fallout that led to #40781 in the 3rd commit. Release Justification: Fixes a bug formerly considered to be a release blocker. Co-authored-by: Andrew Werner <[email protected]>
Build succeeded |
This PR adds back the changes in #40581 and deals with the fallout that led to #40781 in the 3rd commit.
Release Justification: Fixes a bug formerly considered to be a release blocker.