[MDEV-23755] safety for upgrades (innodb) and packaging Created: 2020-09-18 Updated: 2024-02-02 Resolved: 2023-01-23 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Packaging, Storage Engine - InnoDB |
| Affects Version/s: | 10.1 |
| Fix Version/s: | N/A |
| Type: | Bug | Priority: | Major |
| Reporter: | Daniel Black | Assignee: | Tuukka Pasanen |
| Resolution: | Fixed | Votes: | 1 |
| Labels: | None | ||
| Attachments: |
|
||||||||||||||||||||||||||||
| Issue Links: |
|
||||||||||||||||||||||||||||
| Description |
|
Outdated notes from zulip chat with marko;
Update by marko: |
| Comments |
| Comment by Marko Mäkelä [ 2021-01-13 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I think that I do not think that it is reasonable to force a change buffer merge (which can take hours) by setting innodb_fast_shutdown=0 before the shutdown. Besides, the change buffer may be corrupted (for example due to | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Otto Kekäläinen [ 2021-01-13 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I've just read https://mariadb.com/kb/en/innodb-system-variables/#innodb_fast_shutdown So we do not want to run `innodb_fast_shutdown=0` on every stop/restart, so we can't inject it permanently into the systemd service (or sysv init) file. For Debian, we could modify the current `invoke-rc.d mariadb stop` in the mariadb-server.preinst/postinst/prerm/postrm scripts. What shall one run on the command line to tell a running mariadbd to stop with `innodb_fast_shutdown=0`? I am not aware of any method. Or do we need to enter the MariaDB console and run some `SET GLOBAL innodb_fast_shutdown=0;` this setting just before we stop the service? This should also work, most of the time the mariadb-server.* scripts have console access. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Daniel Black [ 2021-01-13 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
For clarity (as a question) so this is largely logic to avoid Its no necessary to change systemd/sysv script. Based on the updated description innodb_max_purge_lag_wait is preferred. So the following as part of the scripts (preinst upgrade?) in the new package operating on the previously still running mariadb version.
Sometime before invoke-rc.d mariadb stop. We need to ignore failures of this command as older versions don't have this variable. marko are you suggesting never do innodb_fast_shutdown=0, not even as a fallback to innodb_max_purge_lag_wait not existing? Won't this leave pre-10.3 versions without an upgrade path due to undo log format changes? Is there an alternate to triggering the purge? Is `set global read_only=1`and waiting for transactions to finish enough to ensure there is no undo log entries that could trigger | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2021-01-14 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
danblack, if innodb_max_purge_lax_wait does not exist, we surely can fall back to slow shutdown. On a second thought, for avoiding Now, what kind of uncommitted transactions can exist in the system?
Let us double-check logs_empty_and_mark_files_at_shutdown() in 10.1 and 10.2. In 10.2, we have the following code there:
In 10.1, the condition is similar. According to this, on the pre-upgrade shutdown, we will also need innodb_read_only_mode=OFF and innodb_force_recovery<3 (ideally it should be 0). But, this is not the whole truth. For recovered transactions that might still be waiting for a rollback in a dedicated thread, we also have the check trx_roll_must_shutdown(), which includes the following:
The rollback of a recovered DDL transaction (there can be at most one) should be finished before server starts up. The final condition is that if innodb_fast_shutdown≠0, we will abort the rollback of recovered normal transactions. In 10.3 (which does not even matter for this upgrade problem), this check is in the function row_undo_step() and it should apply to innodb_fast_shutdown=3 (In It looks like the upgrade scripts would have to implement a polling loop that the number of recovered transactions is zero. It would also be good to check that no transactions exist in XA PREPARE state, so that an useless infinite wait can be avoided. Then, a shutdown with the following settings should be fine:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Daniel Black [ 2021-01-14 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
thanks for the detail. I tested `set global read_only=1` and it doesn't wait for transactions to complete. It does ensure that existing transactions are doomed when they hit commit ERROR 1290 (HY000): The MariaDB server is running with the --read-only option so it cannot execute this statement (but not XA transactions - bug MDEV-24587) select SUM(trx_rows_modified) from information_schema.INNODB_TRX; can show if undo records exist. This also included XA prepare statements exist on innodb. innodb_read_only_mode and innodb_force_recovery aren't dynamic which helps, we can abort an upgrade if those are outside bounds.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2021-01-14 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
danblack, please note that read_only does not prevent InnoDB from internally modifying data (purging transaction history, merging buffered changes, and so on). The setting innodb_read_only would be for that. Sorry, I made a mistake earlier regarding the parameter name. I am not a fan of the MySQL practice of naming the underlying variables differently:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Otto Kekäläinen [ 2021-02-03 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I am experimenting this in https://github.com/MariaDB/server/commit/ab989c82231cabddf0db0fb9f8808984133a4eee Can you provide some test case to use to verify that `innodb_fast_shutdown` did indeed run etc? I don't like adding features without some kind of tests to verify them. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Daniel Black [ 2021-02-03 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
On innodb_fast_shutdown: 10.3 onwards will have an message InnoDB: to purge {num} transactions in the error log on shutdown if a slow shutdown is occurring. For this there actually needs to be transactions to purge. For CI test something like the following is sufficient:
Then package upgrade/replace. On the patch do you need to use /etc/mysql/debian.cnf if it exists for client auth? (I'm re-reading the above to see what a minimal (impract) form of script would like) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Daniel Black [ 2021-02-04 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
otto's approach here (as I guess it) is to get something into downstream debian for the next release on 10.5. For simplicity keeping that as innodb_fast_shutdown=0 will save significant version checks and script complexity. marko should innodb_fast_shutdown=0 be limited to major upgrades only? (like the following suggests https://mariadb.com/kb/en/upgrading-between-major-mariadb-versions/#requirements-for-doing-an-upgrade-between-major-versions). I think it would really help some users if there is time to implement it. If so prerm (someone is upgrade from us) needs
preinst upgrade $oldversion prerm remove otto your postinst configure implementation looks odd to see why you've added it here? Sorry if I'm missing something. ref: https://www.debian.org/doc/debian-policy/ap-flowcharts.html Next step, even minor upgrades should ensure no insert_undo on shutdown to avoid
marko is IS.INNODB_TRX's trx_rows_modified the most script accessible way to see if insert undo records exist (even though these may be other records?) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2021-02-06 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
danblack, like I wrote earlier, I believe that it should suffice to ensure that no uncommitted transactions will exist when upgrading from older versions to 10.3 or later. That is, innodb_fast_shutdown=0 should not be necessary. What is necessary is to ensure that all transactions have been rolled back before shutting down the old version. This must be tested extensively, of course. I think that it is a reasonable requirement to always ensure that no transactions exist before upgrading between major versions. An existing transaction in XA PREPARE state could hold locks that would make some upgrade script hang. This assumes that minor version upgrades are not going to execute any DDL scripts. Maybe it is not too intrusive to always require that no transactions are pending before upgrading? A clean shutdown is always recommended (instead of killing the server), especially because some versions refuse to perform a crash-upgrade from older versions. The most recent example is 10.5 (due to Now, how to detect transactions that are active? I was thinking that one way could be to parse the SHOW ENGINE INNODB STATUS and look for the word ACTIVE, as it is displayed by trx_print_low(). This should include also recovered transactions that are being rolled in the background, or remain in XA PREPARE state. I think that your suggestion should work even better. I found the following code:
This will initialize information_schema.innodb_trx.trx_rows_modified. If there are no rows to be rolled back, Once you have something, I think that elenst should incorporate it in her upgrade testing framework, to validate these assumptions and check that | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Otto Kekäläinen [ 2021-02-10 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Docs about Debian maintainer scripts: https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html It might be possible to hook into the mechanism that calls the `mariadb-server-10.5.preinst upgrade <old-version>` and then issue commands to the existing server (if still running) to do a different kind of shutdown on minor and major upgrades. Note that there is also the `dh_systemd_start --restart-after-upgrade` customization to consider in `debian/rules`. You can debug what the maintainer scripts do by running `DEBIAN_SCRIPT_TRACE=1` before running `apt install` or `apt upgrade`. I Just did it for a 10.5.6 install and then single plugin upgrade to 10.5.8 (which triggers a restart of mariadbd) and a full server 10.5.6-1 (Debian) to 10.5.8-1 (Debian) upgrade. Logs attached debian-script-debug-upgrade-server-2.txt Breakdown of maintainer scripts and their arguments run on mariadb-server install:
Breakdown of maintainer scripts and their arguments run on mariadb-plugin-spider upgrade:
Breakdown of maintainer scripts and their arguments run on mariadb-server-10.5 upgrade:
Note: mariadb-server-10.5.prerm does not contain code to be debugged with DEBIAN_SCRIPT_TRACE, so not visible in lists above. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Otto Kekäläinen [ 2021-05-09 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
marko danblack I've done some experiments on this topic in https://github.com/ottok/mariadb/commit/50b1bc808a2b0d76ae02bafa2f333ae3b66bbe67 However, to be able to complete this, you need to be very clear on what is the actual problem we try to fix here and what is the correct way to initiate a graceful shutdown on MariaDB. Since the information is useful beyond just this Jira issue, I suggest you write a knowledge base article that clearly states:
For the purpose of this Jira issue, I personally would also like to know:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2021-05-17 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
otto, thank you for taking a look at this. The main motivation for a clean shutdown before upgrade is to avoid hitting One way to repeat the problem should be to kill the pre-10.3 server during a write workload, and then upgrade to 10.3. When upgrading from a version earlier than 10.2, or to a version later than 10.3, startup after such a crash would be refused because the redo log would not be empty. That can be ‘fixed’ by starting the old server with innodb_force_recovery=3 and initiating a clean shutdown. After that step, the undo logs would still be in the problematic state, but the redo log would look clean and the server should be able to repeat I hope that elenst can confirm or deny my above claim that I think that the the following constraints must be upheld during upgrade:
The redo log format was radically changed in 10.2 (with the introduction of the log file format identifier that I implemented in MySQL 5.7.9) and 10.5 ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Otto Kekäläinen [ 2021-05-17 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thanks Marko for the info, but please consider documenting the | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2021-05-17 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
We will not have that clarify before my claim has been validated by testing an upgrade, by elenst when time permits. I think that it suffices to test an upgrade from 10.2 to 10.3. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Otto Kekäläinen [ 2021-05-21 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Based on the discussion in https://jira.mariadb.org/browse/MDEV-22373 that is another potential case where innodb_fast_shutdown=0 could have prevented issues on next startup.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Elena Stepanova [ 2021-05-22 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
marko wrote:
What you describe as a workaround is the exact test scenario described in
If there is any doubt in the accuracy of the description, it can be easily checked on the datadir attached to
Then I shut it down, it said:
Then I started recent 10.3 on the same datadir. It said:
So, I can neither confirm nor deny your claim:
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2021-05-24 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
elenst, sorry, I used confusing language. I had put the word ‘fixed’ in quotes, because I think that the step of making the write-ahead log (redo log) clean is artificial and hopefully not executed by any serious DBA. The only purpose of the extra step of restarting the old server with innodb_force_recovery=3 is to make the redo log logically empty while retaining incomplete transactions in the undo logs. My claim (which I would like you to confirm or refute) is that if there is an orderly shutdown of the 10.2 or earlier server (with innodb_force_recovery<3 and innodb_fast_shutdown≠2), then the 10.3 or later server should not hit If my claim holds, we could make the upgrade process more robust by making the 10.3 or later server refuse to start up when an incomplete transaction in the pre- | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Elena Stepanova [ 2021-05-25 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I have sampled recorded failures attributed to For the directory attached to I think these two evidences combined are a good indication that your theory is correct and can be acted upon. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2021-05-25 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
greenman, can you please update the knowledge base according to my latest comments above? otto and danblack, when it comes to upgrading, I would recommend the following. Hopefully you can implement this:
Note: starting with 10.3 there is also the option innodb_fast_shutdown=3, which ends in a logically empty redo log, but skips the rollback of any transactions. While I do not anticipate any trouble related to using that option, it might be better to always use innodb_fast_shutdown=1 before upgrading | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2021-06-21 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2021-07-26 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
danblack, I hope that you can review our upgrade scripts that they correspond to what I suggested here and in I think that it would be nice to ensure that ‘failure is an option’. First, if the server hangs on shutdown, or if some incompatible option (such as innodb_force_recovery) was in effect, maybe the upgrade script should abort just there. Ultimately, it is the upgraded server’s duty to perform further consistency checks and refuse startup if appropriate. Should the upgraded server fail to start up, then I think that manual intervention by the system administrator will be needed: For example, install an old version of the server again and try to perform a proper shutdown. I do not think that we should attempt to implement rollback to an older version. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Otto Kekäläinen [ 2021-08-23 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Note illuusio that among the 17 comments in this issue there is a prototype in https://jira.mariadb.org/browse/MDEV-23755?focusedCommentId=188808&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-188808 - you don't need to start from scratch on this one. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Tuukka Pasanen [ 2021-08-25 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
otto As commented in Pull and reading what 'innodb_max_purge_lag_wait' should do I'm favor to believe that it's not actually needed as it but then if it doesn't make problem worse then extra care problems like this is not bad thing. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Tuukka Pasanen [ 2023-01-23 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
PR is closed and this seems be in order |