-
Notifications
You must be signed in to change notification settings - Fork 512
sql-150: reclaim storage metadata for ephemeral items on crash #38160
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
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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 | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1334,6 +1334,36 @@ def wait_for(sql: str, expected: list[tuple], what: str) -> None: | |||||||||||||||
| cur_b.execute("SELECT count(*) FROM tv") | ||||||||||||||||
| assert cur_b.fetchall() == [(1,)], "session b lost its own temporary items" | ||||||||||||||||
|
|
||||||||||||||||
| # A comment on a temporary item is a durable catalog row too, and item ids | ||||||||||||||||
| # are reused, so reclamation must drop it or it can re-attach to an | ||||||||||||||||
| # unrelated later object. | ||||||||||||||||
| cur_b.execute("COMMENT ON TABLE tt IS 'crash victim'") | ||||||||||||||||
| temp_comment_count = """ | ||||||||||||||||
| SELECT count(*) FROM mz_internal.mz_catalog_raw | ||||||||||||||||
| WHERE data->>'kind' = 'Comment' | ||||||||||||||||
| AND data->'value'->>'comment' = 'crash victim' | ||||||||||||||||
| """ | ||||||||||||||||
| comments = c.sql_query(temp_comment_count, port=6877, user="mz_system") | ||||||||||||||||
| assert comments == [(1,)], f"the temp table's comment was not written: {comments}" | ||||||||||||||||
|
|
||||||||||||||||
| # Capture the shard backing session b's temp table: the metadata row of | ||||||||||||||||
| # the one remaining ephemeral item that has storage (the temp view has | ||||||||||||||||
| # none). It is what boot-time reclamation must clean up after the kill. | ||||||||||||||||
| shards = c.sql_query( | ||||||||||||||||
| """SELECT m.data->'value'->>'shard' | ||||||||||||||||
| FROM mz_internal.mz_catalog_raw m | ||||||||||||||||
| WHERE m.data->>'kind' = 'StorageCollectionMetadata' | ||||||||||||||||
| AND m.data->'key'->'id' IN ( | ||||||||||||||||
| SELECT i.data->'value'->'global_id' | ||||||||||||||||
| FROM mz_internal.mz_catalog_raw i | ||||||||||||||||
| WHERE i.data->>'kind' = 'Item' | ||||||||||||||||
| AND i.data->'value'->>'ephemeral_owner_session' IS NOT NULL)""", | ||||||||||||||||
| port=6877, | ||||||||||||||||
| user="mz_system", | ||||||||||||||||
| ) | ||||||||||||||||
| assert len(shards) == 1, f"expected one ephemeral storage mapping: {shards}" | ||||||||||||||||
| temp_shard = shards[0][0] | ||||||||||||||||
|
|
||||||||||||||||
| # --- kill -9, with session b's items still live --------------------------- | ||||||||||||||||
|
|
||||||||||||||||
| c.kill("materialized") | ||||||||||||||||
|
|
@@ -1366,6 +1396,39 @@ def wait_for(sql: str, expected: list[tuple], what: str) -> None: | |||||||||||||||
| (0,) | ||||||||||||||||
| ], f"ephemeral catalog items survived the restart: {ephemeral}" | ||||||||||||||||
|
|
||||||||||||||||
| # The temp table's storage mapping must have moved to the finalization | ||||||||||||||||
| # WAL in the same reclamation, else the metadata row and its persist | ||||||||||||||||
| # shard would leak forever. Both rows are stable to assert on here: the | ||||||||||||||||
| # metadata deletion is permanent, and the WAL row survives until the | ||||||||||||||||
| # next committed catalog transaction, which cannot have happened because | ||||||||||||||||
| # nothing has run DDL since the restart. | ||||||||||||||||
| metadata = c.sql_query( | ||||||||||||||||
| f"""SELECT count(*) FROM mz_internal.mz_catalog_raw | ||||||||||||||||
| WHERE data->>'kind' = 'StorageCollectionMetadata' | ||||||||||||||||
| AND data->'value'->>'shard' = '{temp_shard}'""", | ||||||||||||||||
| port=6877, | ||||||||||||||||
| user="mz_system", | ||||||||||||||||
| ) | ||||||||||||||||
| assert metadata == [ | ||||||||||||||||
| (0,) | ||||||||||||||||
| ], f"temp table's storage metadata survived the restart: {temp_shard}" | ||||||||||||||||
| unfinalized = c.sql_query( | ||||||||||||||||
| f"""SELECT count(*) FROM mz_internal.mz_catalog_raw | ||||||||||||||||
| WHERE data->>'kind' = 'UnfinalizedShard' | ||||||||||||||||
| AND data->'key'->>'shard' = '{temp_shard}'""", | ||||||||||||||||
| port=6877, | ||||||||||||||||
| user="mz_system", | ||||||||||||||||
| ) | ||||||||||||||||
| assert unfinalized == [ | ||||||||||||||||
| (1,) | ||||||||||||||||
| ], f"temp table's shard was not enqueued for finalization: {temp_shard}" | ||||||||||||||||
|
|
||||||||||||||||
| # The comment row dies with its item. | ||||||||||||||||
| comments = c.sql_query(temp_comment_count, port=6877, user="mz_system") | ||||||||||||||||
|
Comment on lines
+1426
to
+1427
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should actually check something
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done! 🙈 |
||||||||||||||||
| assert comments == [ | ||||||||||||||||
| (0,) | ||||||||||||||||
| ], f"the temp table's comment survived the restart: {comments}" | ||||||||||||||||
|
|
||||||||||||||||
| # conn_b's socket died with the process; closing is bookkeeping only. | ||||||||||||||||
| try: | ||||||||||||||||
| conn_b.close() | ||||||||||||||||
|
|
||||||||||||||||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
👍