Bug#119037 Fix OOM during MySQL upgrade with large number of tables #631
+4 −0
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.
Description
A unbounded memory usage issue has been identified in the
check_table_funsfunction, introduced in commit 7c0dda9. This function is responsible for validating SQL functions within table definitions during a database upgrade. It occurs because tables that are opened for validation are not subsequently closed. For databases with a very large number of tables, this leads to uncontrolled memory growth, eventually causing the MySQL server to be terminated by the operating system's OOM (Out of Memory) killer.The issue stems from the fact that
check_table_funsiterates through all tables and callsopen_tablefor each one, but fails to call a corresponding function to close the tables and release the associated memory. This behavior was not present in previous, and as a result, upgrades on databases with a high table count were significantly faster and consumed a stable amount of memory.How to recreate the issue
The bug can be reproduced by performing an upgrade from MySQL 8.0.40 to 8.0.42 on a server with a schema containing a large number of tables (e.g., ~1 million).
During the upgrade process, memory consumption will steadily increase until the server is terminated by the OOM killer. As a point of comparison, upgrading the same database from 8.0.40 to 8.0.41 completes successfully in a much shorter time and without excessive memory usage.
Fix
The provided patch resolves the unbounded memory usage issue by ensuring that each table is closed immediately after its validation is complete. This is achieved by adding a call to
close_thread_tablewithin the loop in thecheck_table_funsfunction, after theopen_tablecall. This change correctly implements the original feature's intent, which was to perform a temporary "try to open" check without lasting side effects. The original code was missing this cleanup step on its success path, leading to uncontrolled memory growth.This fix is safe. The entire upgrade check runs in an isolated bootstrap thread that starts with no open tables. Furthermore, the operation is precise:
open_tableadds a handle to the head of a list, andclose_thread_tableremoves that exact same handle. Since open_table does not recursively open handles for dependencies like triggers or foreign keys, this single close should be sufficient to release all resources acquired in the loop, preventing the OOM error and allowing the upgrade to complete successfully.Testing
The fix has been verified by running the
main.dd_upgrade_36890891MTR test. Furthermore, the scenario described in the bug report was recreated. Without the patch, the upgrade failed due to an OOM error. With the patch applied, the upgrade to 8.0.42 completed successfully without consuming an excessive amount of memory, confirming the effectiveness of the fix.This contribution is under the OCA signed by Amazon and covering submissions to the MySQL project.