Upgrading MySQL with minimal downtime through Replication

Problem

With the release of MySQL 5.1, many DBAs are going to be scheduling downtime to upgrade their MySQL Server. As with all upgrades between major version numbers, it requires one of two upgrade paths:

  • Dump/reload: The safest method of upgrading, but it takes out your server for quite some time, especially if you have a large data set.
  • mysql_upgrade: A much faster method, but it can still be slow for very large data sets.

I’m here to present a third option. It requires minimal application downtime, and is reasonably simple to prepare for and perform.

Preparation

First of all, you’re going to need a second server (which I’ll refer to as S2). It will act as a ‘stand-in’, while the main server (which I’ll refer to as S1) is upgraded. Once S2 is ready to go, you can begin the preparation:

  • If you haven’t already, enable Binary Logging on S1. We will need it to act as a replication Master.
  • Add an extra bit of functionality to your backup procedure. You will need to store the Binary Log position from when the backup was taken.
    • If you’re using mysqldump, simply add the –master-data option to your mysqldump call.
    • If you’re using InnoDB Hot Backup, there’s no need to make a change.  The Binary Log position is shown when you restore the backup.
    • For other backup methods, you will probably need to get the Binary Log position manually:
      mysql> FLUSH TABLES WITH READ LOCK;
      mysql> SHOW MASTER STATUS;
      (Perform backup now...)
      mysql> UNLOCK TABLES;

    Once you have a backup with the corresponding Binary Log position, you can setup S2:

    • Install MySQL 5.1 on S2.
    • Restore the backup from S1 to S2.
    • Create the Slave user on S1.
    • Enter the Slave settings on S2. You should familiarise yourself with the Replication documentation.
    • Enable Binary Logging on S2. We’ll need this during the upgrade process.
    • Setup S2 as a Slave of S1:
      • If you used mysqldump for the backup, you will need to run the following query:
        mysql> CHANGE MASTER TO MASTER_HOST='S2.ip.address', MASTER_USER='repl_user', MASTER_PASSWORD='repl_password';
      • For any other method, you’ll need to specify the Binary Log position as well:
        mysql> CHANGE MASTER TO MASTER_HOST='S2.ip.address', MASTER_USER='repl_user', MASTER_PASSWORD='repl_password', MASTER_LOG_FILE='mysql-bin.nnnnnnn', MASTER_LOG_POS=mmmmmmmm;
    • Start the Slave on S2:
      mysql> START SLAVE;

    The major pre-upgrade work is now complete.

    Upgrade

    Just before beginning the upgrade, take a backup of S2. For speed, I’d recommend running the following queries, then shutting down the MySQL server and copying the data files for the backup.

    mysql> STOP SLAVE;
    mysql> SHOW MASTER STATUS;

    Once the backup is complete, restart S2 and let it catch up with S1 again.

    When you’re ready to begin the upgrade, you will need a minor outage. Stop your application, and let S2 catch up with S1. Once it has caught up, they will have identical data. So, switch your application to using S2 instead of S1. Your application can continue running unaffected while you upgrade S1 server.

    • Stop the Slave process on S2:
      mysql> STOP SLAVE;
    • Stop S1.
    • Upgrade S1 to MySQL 5.1.
    • Move the S1 data files to a backup location.
    • Move the backup from S2 into S1’s data directory.
    • Start S2.
    • Setup S1 as a Slave to S2, same as when we made S2 a Slave of S1.
    • Let S1 catch up with S2. When it has caught up, stop your application, and make sure S1 is still caught up with S2.
    • Switch your application back to using S1.

    Complete! Hooray! You just need to run a couple of queries on S1 to clean up the Slave settings:

    mysql> STOP SLAVE;
    mysql> CHANGE MASTER TO MASTER_HOST='';

    Conclusion

    You can keep the outage to only a few minutes while performing this upgrade, removing the need for potentially expensive downtime. If you need the downtime to be zero, you probably want to be looking at a Circular Replication system, though that’s getting a little outside of this blog post.

8 comments

    1. If you have the spare capacity, certainly. Restoring the S1 backup to the S2 Slave will be particularly processor intensive (mysqldump always is, data file restoration will require mysql_upgrade), so it could impact your production database. This is the main reason why I’d recommend a second server.

  1. This isn’t actually a third option. It’s an architecture that makes the downtime of upgrading less felt by end users — but each server still has the downtime needed for upgrade.

    You’re not actually lessening the downtime for the server, just for the end user. Note that when upgrading to a new release series (ie, major version, ie 5.0->5.1) MySQL recommends doing a logical export with mysqldump and importing.

    You may find the comprehensive post on everything new in 5.1 helpful.

    1. For many uses of MySQL, what the end user sees (websites, etc) is where downtime is measured.

      What makes this a third option is the ease of allocating an extra server. Most physical hosts have a turnaround measured in hours to setup a new box, VPS hosts measure it in minutes. With the growing prevalence of “pay as you use it” Virtual Hosts (EC2, etc), it’s not unreasonable to allocate an extra server for a day or two, then drop it.

      I agree that for larger users with their own racks or data centers, this won’t be useful. But, I’d expect them to have their own rolling upgrade process anyway.

      1. *nod* I agree with the point about downtime.

        To be clear, you are showing the 2nd option — when you upgrade to 5.1 you still have to use mysql_upgrade, because there are important changes that have to be made to the mysql system tables.

        You’re just showing a really good architectural solution to minimize downtime. But you still have to use mysql_upgrade.

  2. Hi Gary!

    Nice article. I like the extra server idea–this would work very nicely on Amazon. I’m a big fan of replication for upgrades.

    You and your readers may want to take a look at Tungsten Replicator for upgrades. It has some interesting capabilities, such as the ability to replicate from a 5.1 server with row replication to 5.0 or previous servers. Helpful for upgrading master/slave setups–matters get trickier when you have multiple servers.

    Also, we will be publishing a component we call the Tungsten SQL Router that implements seamless failover so that applications don’t even see a break when switching. There are some rules, of course, but it’s still quite cool.

    The software is in open source and available at http://community.continuent.com. The SQL router should be published shortly.

    Thanks and Cheers, Robert
    (Continuent CTO)

  3. Hi
    Nice article. But at the end isn’t there a mixup with S1 and S2? In my opinion the correct is
    # Stop S1.
    # Upgrade S1 to MySQL 5.1.
    # Move the S1 data files to a backup location.
    # Move the backup from S2 into S1’s data directory.
    # Start S1.
    # Setup S1 as a Slave to S2, same as when we made S2 a Slave of S1.
    # Let S1 catch up with S2. When it has caught up, stop your application, and make sure S1 is still caught up with S2.
    # Switch your application back to using S1.
    # Stop replication from S2 to S1

    Have I misunderstand something?
    Best regards Vilhelm

Comments are closed.