Inplace upgrade from MySQL 5.7 to MySQL 8.0

I recently had the misfortune of spending a week at work tasked with testing how we can upgrade our ancient MySQL databases into the modern era only using the inbuilt tools without any utilities (due to a highly locked-down environment). I thought it best to share a clean version of docos so if someone else is in the same niche-ish situation, they’re able to navigate the upgrade without trawling 20 forum posts and docs.

You’ll see a lot of people reference the ‘sql_upgrade’ utility, this however was depreciated in 2019 with v8.0.16 and the server now will upgrade any outdated databases on start-up depending on the –upgrade option.
Another helpful utility that may be of use if you’re upgrading to a version >= 8.0.4 is “Upgrade checker”, see MySQL Shell 8.0.4: Introducing “Upgrade checker” utility.

While v8.0 IS backwards compatible with v5.7, there were changes to the storage engine used for multiple core system tables (mysql, information_schema, performance_schema, sys) and new/depreciated tables between versions. Because of this the database contents needs upgrading too.

The plan is then to create a Source/Replica (or Slave/Master if we’re talking in v5.7 terms) between the two versions, then disable the old Source and update the DNS CNAME record to point to our new source. The backup replicas will of course need to be updated because v5.7 aren’t forwards compatible.

Current setup & Assumptions

  • Worth noting a few settings and environment details in this setup.
  • You have a functional MySQL v5.7.* server you’re replicating from
  • Other MySQL v5.7.* are replicating from this source server
  • Not necessarily relevant to upgrade but important if they exist
  • Stripped down basic ‘my.cnf‘ config file
  • The MySQL directory layout is as follows
  • A shared DNS CNAME is used to point to the source server
  • Not strictly relevant to the overall setup but all servers operate on FreeBSD 12.2

Procedure

Initialise

First things, our test machine (Server B, who will be our future Source) should be initialised and replicating from source (A) as cleanly as possible, a ‘cold start’.

  • Clear out the ‘./data‘ directory

Initialise the database

MySQL Installation Guide | v5.7 | 9.1 Initializing the Data Directory

A “temporary password” will be provided in this output which is flagged as expired. It has to be changed once you gain access to execute any basic commands.

  • Start the ‘mysql-server‘ service.
  • Access the SQL shell and change the expired password
  • If successful access to shell, exit and continue to import the database

MySQL 5.7 Reference Manual | v5.7 | 4.5.4 mysqldump — A Database Backup Program

This will update all user logins/privileges and populate the ‘./data’ directory.

  • Test the database population by querying it

Upgrading

As mentioned in the beginning, while MySQL is backwards compatible between versions 8.0 and 5.7, it isn’t simply plug n play. To avoid these issues, allow the MySQL server to upgrade the database itself in-place before beginning operations/replication.
The default value for the MySQL Server option –upgrade is AUTO so we can upgrade the version while the database is imported then restart the server.

For better logging of this upgrade it’s worth adding: ‘log_error_verbosity=3‘ to the ‘my.cnf‘ file (in-case anything goes wrong).

Assuming the initialisation went smoothly and the databases are imported correctly, continue with the below steps:

  • Stop the service, then upgrade the MySQL server version to 8.0
  • Restart the service and review the ‘./data/hostname.ci.com.au.err‘ logs and wait.

This upgrade may take a number of minutes to complete but you can review it’s progress in the log file (especially if ‘log_error_verbosity‘ is set to 3).

NOTE: The upgrade duration depends on database size. Roughly 5-15 minutes for small databases (<10GB), and proportionally longer for larger datasets. Do not interrupt this process otherwise it’ll corrupt and you’ll need to start again. While this upgrade is taking place, don’t attempt to start the service until it’s complete otherwise duplicate processes will be created and you’ll see similar errors to below

You’ll know the upgrade is complete once you see the below line(s).

  • Run some checks to ensure the validity of the databases.

Make sure the user tables are the same between servers. There may be some changes to the core system tables but these are due to the version increase. Some sanity checks you can run is comparing the checksum value:

Swapping the Source and Replica

Now is the tricky part, this section should be done during quiet or off-peak hours to ensure the minimum amount of disturbances to any clients using the databases. Now because Server A is the live source and constantly receiving updates, we need the most recent data available before we make the swap.

First, verify if GTID is enabled on both servers:

If the result shows ‘ON’ for both servers, follow the GTID instructions. Otherwise, use log file positioning.

NOTE: The below examples use passwords in plaintext for clarity. In production consider:

  • MySQL’s CHANGE MASTER TO with MASTER_PASSWORD from a secure credential store
  • Encrypted connections (MASTER_SSL=1)
  • Restricted access to configuration files

GTID

If Global Transaction Identifier (GTID) is enabled for both hosts, the slave will automatically know where to pick up from and greatly simplifies this step. Run the below command to point to source.

Log file positioning

If GTID is disabled, so the binary log file positions need to be retrieved from the backup we restored. To find these, read the backup file and on the ~20th line you should see something like this:

We can use this information to begin replication. Connect to the MySQL shell of the newly v8.0 machine (B) and run the below:

Note in the above command ‘repl’ is a user on the Source with replication privileges.

Do normal checks to ensure that the replication is functioning (e.g. ‘Slave_SQL_Running_State‘ is happily waiting for more updates).

If replication fails to start, verify:

  • The log file and position are correct in the dump file
  • The ‘repl‘ user (or whatever use you’re using for replication) exists on Server A with replication privileges
  • Network is functioning between servers (test with ‘telnet serverA 3306‘)
  • Binary logging is enabled on Server A (‘SHOW VARIABLES LIKE ‘log_bin’;‘)

We’ve now created the below setup:

Swap in the new Source

Now that we have the most updated information available to Server B on MySQL v8.0, we can swap the old version out. If you make a mistake here you can always bring up the old source (Server A) as the main source again.

  • Stop the old source from reading:
  • Reset the slave database’s slave config, allowing it to believe it’s a master:
  • Update the CNAME to the new source (Server B)

Now that’s done you can move onto the on/offsite replicas. These can be done during office hours or whenever as there is already a valid working connection for the MySQL clients.

The final setup layout doesn’t change by much, the CNAME just now points to Server B instead of A.

The On/Offsite Replicas

During the swap, the backups servers C and D (the existing v5.7 replicas) will continue replicating from A until the CNAME changes, then they will break. Until these machines are updated they cannot replicate because as mentioned previously, v5.7 cannot replicate from v8.0. They must be:

  • Upgraded to v8.0 using the same procedure as Server B

OR

  • Replaced with new v8.0 instances replicating from Server B

Do not attempt to point v5.7 replicas at a v8.0 source – they are not forwards compatible.

Rollback Plan

If anything starts to go wrong, remember you can always fall back to Server A and try again. As below:

  • Set Server B to read-only
  • Update the CNAME back to Server A
  • Re-enable writes on Server A if you disabled them
  • Troubleshoot and try again

Conclusion

I hope this was at least slightly useful to anyone in the same boat as myself and helps with any upgrading projects you’re endeavouring.

Remember to keep Server A running as a backup for at least 24-48 hours (or longer!) after the upgrade to ensure the setup is stable before fully decommissioning.

Leave a Reply