Skip to content
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

backupccl: handle sequence ownership remapping logic for restore #50949

Merged
merged 1 commit into from Jul 7, 2020

Conversation

arulajmani
Copy link
Collaborator

Previously, we would restore sequence descriptors/table descriptors as
is, without remapping the ownership dependency to the new IDs. This
meant sequence ownership was broken post restore. This PR fixes that.

When sequences with owners or tables that have columns that own
sequences are restored:

  • If both the owned sequence and the owning table are being restored,
    the ownership is remapped.
  • If just the sequence is restored, the user receives an error to use
    the skip_missing_sequence_owners flag. If the flag is provided, the
    sequence is restored without any owner.
  • If just the table is restored, the user receives an error to use the
    skip_missing_sequence_owners flag. If the flag is provided, the table
    is restored with the table column that previously owned the sequence no
    longer owning that sequence.

Fixes #50781

Release note (enterprise change): Restore now has a new option
skip_missing_sequence_owners that must be supplied when restoring
only the table/sequence that was previously
a sequence owner/owned by a table.
Additionally, this fixes a bug where ownership relationships would not
be remapped after a restore.

@arulajmani arulajmani requested review from pbardea, rohany and a team July 2, 2020 23:34
@cockroach-teamcity
Copy link
Member

This change is Reviewable

Copy link
Contributor

@rohany rohany left a comment

Choose a reason for hiding this comment

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

Overall this LGTM, but paul should take a look

`RESTORE TABLE seq FROM $1`, backupLoc)

newDB.Exec(t, `RESTORE TABLE seq FROM $1 WITH skip_missing_sequence_owners`, backupLoc)
seqDesc := sqlbase.TestingGetTableDescriptor(kvDB, keys.SystemSQLCodec, "d", "seq")
Copy link
Contributor

Choose a reason for hiding this comment

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

So why do we allow this? aren't things just busted at this point?

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, why would things be busted? I guess I'm confused at what the expected behavior of a sequence that had its owner removed is? I'd expect this would have the same effect as ALTER SEQUENCE d.seq OWNED BY NONE, which (naively) seems fine

origDB.Exec(t, `BACKUP DATABASE d TO $1`, backupLoc)

// Setup for cross-database ownership backup-restore tests.
origDB.Exec(t, `CREATE DATABASE d2`)
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be clearer to do this initialization closer to the tests that use them?

origDB.Exec(t, `BACKUP DATABASE d2 TO $1`, backupLocD2)
origDB.Exec(t, `BACKUP DATABASE d3 TO $1`, backupLocD3)

t.Run("test sequence owned by table in the same database", func(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Overall, I'd like to see a few more comments on these tests -- like what are we trying to do, what should we see etc.

}
})

t.Run("test restoring two databases removes cross-database ownership dependency",
Copy link
Contributor

Choose a reason for hiding this comment

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

This is really counterintuitive, but I guess any sort of cross database reference handling is strange.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure that it's super odd since that during the first restore you'd be explicitly removing the dependency.

I would like to see some tests restoring both databases at the same time and ensuring that the dependency is still there.

Copy link
Contributor

@pbardea pbardea left a comment

Choose a reason for hiding this comment

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

Thanks for grabbing this! Implementation generally looks good - just left a few test related comments.

}
})

t.Run("test restoring two databases removes cross-database ownership dependency",
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure that it's super odd since that during the first restore you'd be explicitly removing the dependency.

I would like to see some tests restoring both databases at the same time and ensuring that the dependency is still there.

newDB := sqlutils.MakeSQLRunner(tc.Conns[0])
kvDB := tc.Server(0).DB()

newDB.ExpectErr(t, `pq: cannot restore`,
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we expand the error message here (and below) to be pq: cannot restore sequence to have more confidence that we're hitting the right error.

`RESTORE TABLE seq FROM $1`, backupLoc)

newDB.Exec(t, `RESTORE TABLE seq FROM $1 WITH skip_missing_sequence_owners`, backupLoc)
seqDesc := sqlbase.TestingGetTableDescriptor(kvDB, keys.SystemSQLCodec, "d", "seq")
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, why would things be busted? I guess I'm confused at what the expected behavior of a sequence that had its owner removed is? I'd expect this would have the same effect as ALTER SEQUENCE d.seq OWNED BY NONE, which (naively) seems fine

// Sequence dependencies inside the database should still be preserved.
sd := sqlbase.TestingGetTableDescriptor(kvDB, keys.SystemSQLCodec, "d3", "seq2")
td := sqlbase.TestingGetTableDescriptor(kvDB, keys.SystemSQLCodec, "d3", "t")
if !sd.SequenceOpts.HasOwner() || sd.SequenceOpts.SequenceOwner.OwnerTableID != td.ID {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we could do:

require.True(t, sd.SequenceOpts.HasOwner())
require.Equal(t, td.ID, sd.SequenceOpts.SequenceOwner.OwnerTableID)

so that if this test fails, it's a bit clearer what is going wrong (same elsewhere in the tests).

origDB.Exec(t, `CREATE DATABASE d`)
origDB.Exec(t, `CREATE TABLE d.t(a int)`)
origDB.Exec(t, `CREATE SEQUENCE d.seq OWNED BY d.t.a`)
origDB.Exec(t, `BACKUP DATABASE d TO $1`, backupLoc)
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we also add a test where we restore all tables back into a different database on the same cluster: something like CREATE DATABASE restore_db; RESTORE d.* FROM $1 WITH into_db='restore_db'; and check that the dependency still holds.

Copy link
Collaborator Author

@arulajmani arulajmani left a comment

Choose a reason for hiding this comment

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

TFTRs! This should be RFAL

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @pbardea and @rohany)


pkg/ccl/backupccl/backup_test.go, line 3633 at r1 (raw file):

Previously, pbardea (Paul Bardea) wrote…

Could we also add a test where we restore all tables back into a different database on the same cluster: something like CREATE DATABASE restore_db; RESTORE d.* FROM $1 WITH into_db='restore_db'; and check that the dependency still holds.

Done.


pkg/ccl/backupccl/backup_test.go, line 3636 at r1 (raw file):

Previously, rohany (Rohan Yadav) wrote…

Would it be clearer to do this initialization closer to the tests that use them?

Moved down.


pkg/ccl/backupccl/backup_test.go, line 3650 at r1 (raw file):

Previously, rohany (Rohan Yadav) wrote…

Overall, I'd like to see a few more comments on these tests -- like what are we trying to do, what should we see etc.

Added comment up top for all tests.


pkg/ccl/backupccl/backup_test.go, line 3680 at r1 (raw file):

Previously, pbardea (Paul Bardea) wrote…

Hmm, why would things be busted? I guess I'm confused at what the expected behavior of a sequence that had its owner removed is? I'd expect this would have the same effect as ALTER SEQUENCE d.seq OWNED BY NONE, which (naively) seems fine

I don't think things are busted if the owner table doesn't exist. A sequence that is owned by a table can be used by another table as well -- so I don't think it's correct to not allow restoring sequences which have owners when the owner is not being restored.

Currently, passing the skip_missing_sequence_owners option will have the same effect as ALTER SEQUENCE d.seq OWNED BY NONE. This seems fine to me if we document what skip_missing_sequence_owners does.


pkg/ccl/backupccl/backup_test.go, line 3748 at r1 (raw file):

Previously, pbardea (Paul Bardea) wrote…

I'm not sure that it's super odd since that during the first restore you'd be explicitly removing the dependency.

I would like to see some tests restoring both databases at the same time and ensuring that the dependency is still there.

This follows how we handle FK cross database references. Added a test to restore both dbs at the same time.


pkg/ccl/backupccl/backup_test.go, line 3756 at r1 (raw file):

Previously, pbardea (Paul Bardea) wrote…

Can we expand the error message here (and below) to be pq: cannot restore sequence to have more confidence that we're hitting the right error.

I had that earlier, but it seems that there isn't a deterministic way to know what is restored first -- the table or the sequence. As both the databases contain a sequence and a table with ownership dependencies, depending on what is processed first the error will be different.

I do agree that it'd be nice to have confidence we're hitting the correct error message, but not sure how we can do it deterministically.


pkg/ccl/backupccl/backup_test.go, line 3777 at r1 (raw file):

Previously, pbardea (Paul Bardea) wrote…

Maybe we could do:

require.True(t, sd.SequenceOpts.HasOwner())
require.Equal(t, td.ID, sd.SequenceOpts.SequenceOwner.OwnerTableID)

so that if this test fails, it's a bit clearer what is going wrong (same elsewhere in the tests).

This is neat! Done.

@arulajmani arulajmani requested a review from pbardea July 6, 2020 21:11
Copy link
Contributor

@pbardea pbardea left a comment

Choose a reason for hiding this comment

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

Reviewed 3 of 4 files at r1.
Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @arulajmani, @pbardea, and @rohany)


pkg/ccl/backupccl/backup_test.go, line 3756 at r1 (raw file):

Previously, arulajmani (Arul Ajmani) wrote…

I had that earlier, but it seems that there isn't a deterministic way to know what is restored first -- the table or the sequence. As both the databases contain a sequence and a table with ownership dependencies, depending on what is processed first the error will be different.

I do agree that it'd be nice to have confidence we're hitting the correct error message, but not sure how we can do it deterministically.

Fair enough, I could imagine that we could provide a regex here that would match either a table depending on a sequence, or a sequence depending on a view if we wanted to make sure it was one of the two errors.


pkg/ccl/backupccl/backup_test.go, line 3663 at r2 (raw file):

	t.Run("test restoring sequence when table does not exist", func(t *testing.T) {
		// When restoring a sequence that is owned by a table, but the owning table

minor nit: the rest of this file has descriptions like this before the t.Run call. Could we move them there for consistency?

Previously, we would restore sequence descriptors/table descriptors as
is, without remapping the ownership dependency to the new IDs. This
meant sequence ownership was broken post restore. This PR fixes that.

When sequences with owners or tables that have columns that own
sequences are restored:
- If both the owned sequence and the owning table are being restored,
the ownership is remapped.
- If just the sequence is restored, the user receives an error to use
the `skip_missing_sequence_owners` flag. If the flag is provided, the
sequence is restored without any owner.
- If just the table is restored, the user receives an error to use the
`skip_missing_sequence_owners` flag. If the flag is provided, the table
is restored with the table column that previously owned the sequence no
longer owning that sequence.

Fixes cockroachdb#50781

Release note (enterprise change): Restore now has a new option
`skip_missing_sequence_owners` that must be supplied when restoring
only the table/sequence that was previously
a sequence owner/owned by a table.
Additionally, this fixes a bug where ownership relationships would not
be remapped after a restore.
Copy link
Collaborator Author

@arulajmani arulajmani left a comment

Choose a reason for hiding this comment

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

Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @pbardea and @rohany)


pkg/ccl/backupccl/backup_test.go, line 3756 at r1 (raw file):

Previously, pbardea (Paul Bardea) wrote…

Fair enough, I could imagine that we could provide a regex here that would match either a table depending on a sequence, or a sequence depending on a view if we wanted to make sure it was one of the two errors.

I like this better, changed!

@arulajmani
Copy link
Collaborator Author

Thanks for the reviews.

bors r=pbardea

@craig
Copy link
Contributor

craig bot commented Jul 7, 2020

Build succeeded

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: sequence owner dependencies are poorly handled in BACKUP/RESTORE
4 participants