Skip to content

MDEV-38839 Assertion (thd->state_flags & Open_tables_state::BACKUPS_A…#5027

Open
pranavktiwari wants to merge 1 commit into12.3from
12.3-MDEV-38839
Open

MDEV-38839 Assertion (thd->state_flags & Open_tables_state::BACKUPS_A…#5027
pranavktiwari wants to merge 1 commit into12.3from
12.3-MDEV-38839

Conversation

@pranavktiwari
Copy link
Copy Markdown

@pranavktiwari pranavktiwari commented May 1, 2026

MDEV-38839: Fix assertion in close_thread_tables on CREATE TABLE...SELECT FOR UPDATE with MyISAM temp table in MIXED binlog mode
Cause: FOR UPDATE on MyISAM temp tables uses a write lock (no row-level locking), incorrectly marking a read as a write. This blocks binlog_truncate_trx_cache() and triggers an assertion.

Fix: In decide_logging_format(), check tbl->updating to detect real writes. For read-only access, mark as STMT_READS_TEMP_NON_TRANS_TABLE instead of write, preventing incorrect behavior.

@pranavktiwari pranavktiwari marked this pull request as draft May 1, 2026 03:29
@pranavktiwari pranavktiwari force-pushed the 12.3-MDEV-38839 branch 4 times, most recently from 58ff35c to afea455 Compare May 3, 2026 01:13
@pranavktiwari pranavktiwari requested a review from Copilot May 4, 2026 02:33
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes binlog table-access classification for CREATE TABLE ... SELECT when the source is a temporary table, aiming to avoid incorrectly treating read-only temp-table access as a write and thereby prevent MIXED-mode binlog cache state from getting stuck and triggering the reported assertion.

Changes:

  • Add a dedicated stmt_writes_to_non_trans_temp_table() helper and use it when marking non-transactional temp-table modifications in binlog write paths.
  • Adjust THD::decide_logging_format() so CREATE TABLE ... SELECT can classify temporary source-table access as reads instead of writes.
  • Add an MTR regression test covering several temp-table engine combinations around CREATE TABLE ... SELECT ... FOR UPDATE.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
sql/sql_lex.h Adds a helper to distinguish non-transactional temp-table writes from general access.
sql/sql_class.cc Changes table-access flag assignment during logging-format analysis for CREATE TABLE.
sql/log.cc Narrows the condition that marks a non-transactional temp table as modified in transactional cache paths.
mysql-test/main/binlog_mdev38839.test Adds a regression test for the reported assertion scenario.
mysql-test/main/binlog_mdev38839.result Records the expected output for the new regression test.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread sql/sql_class.cc Outdated
Comment thread mysql-test/main/binlog_mdev38839.test
@pranavktiwari pranavktiwari marked this pull request as ready for review May 4, 2026 08:58
Comment thread mysql-test/main/binlog_mdev38839.test Outdated

--echo #
--echo # Test case 4: InnoDB temp source, InnoDB target - should not crash
--echo #
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why there are so many test cases? What is the difference in the patch for them?

Copy link
Copy Markdown
Author

@pranavktiwari pranavktiwari May 4, 2026

Choose a reason for hiding this comment

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

I made these 5 different cases ti understand the existing behavior before start fixing.
Once I was sure why this particular test case is failing I started with my changes.
I did not remove them because they should also pass after the code changes.

There is no difference. It just to make sure changes did not affect other scenarios.

Copy link
Copy Markdown
Contributor

@midenok midenok May 4, 2026

Choose a reason for hiding this comment

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

Please, do not make redundant test cases if they don't cover any unique parts of the code.

Comment thread sql/sql_class.cc Outdated
LEX::STMT_WRITES_TEMP_NON_TRANS_TABLE);
{
if (lex->sql_command == SQLCOM_CREATE_TABLE &&
!lex->tmp_table() && !found_first_not_own_table)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These conditions should be explained in comment. I think you aim for table in SELECT. There should be select_lex in TABLE_LIST, so maybe it is worth checking its existence.

Comment thread sql/sql_class.cc Outdated
!lex->tmp_table() && !found_first_not_own_table)
lex->set_stmt_accessed_table(trans ?
LEX::STMT_READS_TEMP_TRANS_TABLE :
LEX::STMT_READS_TEMP_NON_TRANS_TABLE);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe it is better to set READS flag in another if() below vvvv. This if (tbl->lock_type >= TL_FIRST_WRITE) should be completely excluded for such tables? But really I'm not sure if not setting WRITES is a good idea. How SELECT .. FOR UPDATE behaves now on slave? Does it lose FOR UPDATE locking? This at least should be explained in commit message if it is not important for slave.

Copy link
Copy Markdown
Contributor

@midenok midenok May 5, 2026

Choose a reason for hiding this comment

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

@pranavktiwari I would still like to get these answers:

How SELECT .. FOR UPDATE behaves now on slave? Does it lose FOR UPDATE locking?

If it is temporary table, does it make sense at all? Worth mentioning in commit message.

Comment thread sql/sql_class.cc

--echo #
--echo # Test case 2: MyISAM temp source, InnoDB target - should not crash
--echo #
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why the two test cases?

Comment thread sql/sql_class.cc Outdated
lex->set_stmt_accessed_table(trans ? LEX::STMT_WRITES_TEMP_TRANS_TABLE :
{
if (tbl->updating)
lex->set_stmt_accessed_table(trans ? LEX::STMT_WRITES_TEMP_TRANS_TABLE :
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks better. Why updating check is only for tmp_table?

Comment thread sql/sql_class.cc Outdated
!lex->tmp_table() && !found_first_not_own_table)
lex->set_stmt_accessed_table(trans ?
LEX::STMT_READS_TEMP_TRANS_TABLE :
LEX::STMT_READS_TEMP_NON_TRANS_TABLE);
Copy link
Copy Markdown
Contributor

@midenok midenok May 5, 2026

Choose a reason for hiding this comment

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

@pranavktiwari I would still like to get these answers:

How SELECT .. FOR UPDATE behaves now on slave? Does it lose FOR UPDATE locking?

If it is temporary table, does it make sense at all? Worth mentioning in commit message.

…LECT FOR UPDATE with MyISAM temp table in MIXED binlog mode

Cause: FOR UPDATE on MyISAM temp tables uses a write lock (no row-level locking), incorrectly marking a read as a write. This blocks binlog_truncate_trx_cache() and triggers an assertion.

Fix: In decide_logging_format(), check tbl->updating to detect real writes. For read-only access, mark as STMT_READS_TEMP_NON_TRANS_TABLE instead of write, preventing incorrect behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

4 participants