MDEV-38822: Fix self-deadlock on CTAS from innodb stats tables#4669
MDEV-38822: Fix self-deadlock on CTAS from innodb stats tables#4669OmarGamal10 wants to merge 1 commit intoMariaDB:10.6from
Conversation
gkodinov
left a comment
There was a problem hiding this comment.
Thank you for your contribution. This is a preliminary review.
In addition to the suggestions below, please squash all of your commits into a single one and make sure it has a message that follows CODING_STANDARDS.md.
| DROP TABLE t1; | ||
| DROP TABLE t2; | ||
| # | ||
| # MDEV-38667 Assertion in diagnostics area on DDL stats timeout |
There was a problem hiding this comment.
I would add a note on MDEV-38667 that the current change further addresses the same issue.
There was a problem hiding this comment.
Do you mean adding a note on the topic on Jira?
There was a problem hiding this comment.
Yes. You are altering the test added through that Jira. So it'd be polite to add an update to it so that people watching it will get a notification.
There was a problem hiding this comment.
Thank you, I added a comment there explaining the change.
| SELECT COUNT(*) as n_rows FROM t; | ||
| n_rows | ||
| 1 | ||
| # For a deterministic test, we wait for the background thread to update the stats for the new table. |
There was a problem hiding this comment.
fwiw, (not really insisting on it and hope the final reviewer would consider it) you could use the DBUG library to produce the effect: https://mariadb.com/docs/server/clients-and-utilities/testing-tools/mariadb-test/the-debug-sync-facility.
I'd give it a couple of hours to try and reproduce it by dipping in DBUG_SYNC points and running two threads in mariadb-test.
| const char *innodb_table_stats= "innodb_table_stats"; | ||
| const char *innodb_index_stats= "innodb_index_stats"; | ||
|
|
||
| if (strstr((const char *) q->str, innodb_table_stats) || |
There was a problem hiding this comment.
That is a terrible way to check if a table is used! Please consider something more robust.
I'd add a thd_sql_is_table_accessed() that would read THD::open_tables and check if the table I need is there.
There was a problem hiding this comment.
Yes, you're right. I overlooked this and focused more on locating the issue itself. I used external linkage in ha_innodb.cc because the public ABI in mysql/plugin.h is normally strict with such additions.
…l.innodb_table_stats Fixes the lock wait timeout when using a CTAS query from InnoDB stats tables. This normally leads to a timeout warning and may skip updating the stats tables if innodb_stats_auto is OFF. This patch identifies this behavior and delegates the stats rebuild to the background pool to avoid self-deadlock.
4933d88 to
63459e6
Compare
Cause
create table t1_stat as SELECT * FROM mysql.innodb_table_stats;causes alock_wait_timeout on updating statswarning.Shared_lockand then attempting to acquire anExclusive_lockon the stats table, resulting in the deadlock.Fix
innodb_stats_auto_recalcglobal variable beingON, which optimistically uses a background thread to update the stats table.Createquery using one of the innodb system tablesmysql.innodb_[table/index]_stats, and delegates the stats rebuild into the background pool regardless of the valueinnodb_stats_auto_recalc.Note: I though about maybe upgrading the shared lock to an exclusive one since the problem is caused by the owner thread only, but this can have other implications for shared behavior, so I went with the above approach.