Upgrade Drupal with Almost Zero Down Time
This site was setup in 2007 with Drupal 5, and it has not been upgraded until today. I did not feel the need to upgrade since this is just a personal blog. A few days ago I wanted to install a module, but Drupal version 6 is required, so I thought it's finally the time to upgrade Drupal. This Drupal upgrade tutorial suggests to first take down the site to upgrade, but I do not like that. It turns out that more than a few days of work are required to bring back a fully functional upgraded site, so taking the site down to upgrade is not a good idea. Below is what I did to upgrade this site from version 5.3 to 6.22 with almost zero down time (well, maybe a few seconds, I didn't time it).
The idea is simple: keep the old site running, setup a test site with a copy of the data, upgrade at test site, fix any problems there, delete the old site when done, and move the test site to be the production site.
First, the old version 5 site needs to be prepared. This means upgrading it from whatever old version to the latest version 5.22. Since this preparation is a minor upgrade, there is no need to bring down the site. Just download the 5.22 tar ball and unpack it over the existing Drupal directory. Run yoursite.com/update.php to update the database. Then download and install update_status module. It will tell you which third-party modules need to be upgraded. Download, unpack, run update.php, repeat, until all modules are at the lastest 5.x versions. Finally, uninstall update_status module, since it is included in Drupal 6 core.
To setup a test site, first create a test.yoursite.com sub-domain using your hosting company's tool. Most Web hosting companies allow sub-domains free of charge, and often provide easy to use tools for managing them (if yours does not, switch host company!). Download and unpack the latest Drupal 6 tar ball to a directory in the Web directory, and point the test.yoursite.com sub-domain to the directory using the hosting company's tool. Point the browser to test.yoursite.come, the Drupal installation page should show up. Now stop, DO NOT go though the installation process, for we are upgrading, not installing.
Because this upgrade method requires two Drupal sites (e.g. one version 5 and one 6) running at the same time, we need to have two databases. Your hosting company should allow the creation of new databases free of charge. First, we need to check the minimum system requirement of the new version of Drupal, especially the database requirement. This can be found at yoursite.com/admin/reports/status page. Here, we are reaping the benefit of keeping the old site running while upgrading the test site: we can look up system information easily.
In my case, the old site is using MySQL version 4.0, which is older than the minimum requirement of Drupal 6. Fortunately, newly created databases using my hosting company's tool are MySQL version 5.0. One thing needs to be careful about is the character encoding of the new database. Make sure it is using utf-8 for charset, and the collation is utf8_general_ci. The later is often not the default, so we need to set it under Operations/Collations in phpMyAdmin, a MySQL management tool most hosting companies provide.
Now we need to roll over the data. This can be done simply with phpMyAdmin. First, login as the primary administrator (the first user, uid=1) at the old Drupal site, and then dump its database using phpMyAdmin. Basically, we need to export all the tables. If the tables are big, you may want to export a few tables at a time. For some tables, such as cache, cache_*, sessions, search_*, and watchdog, you may want to export the structure only, instead of both structure and data, as these data can be dynamically regenerated. The exported database consists of a bunch of compressed SQL text files. Using phpMyAdmin, browse to the newly created empty database, run these SQL files to import all the tables.
After the new database is ready, we need to edit the new Drupal directory's sites/default/settings.php file. This file is not there initially. There are two ways to create it: a). Copy the file from old Drupal directory if there are a lot of customizations done there; b). Rename the file default.settings.php to settings.php. I took the later approach. Now in settings.php, find the line looks like \$db_url = 'mysql://username:password@hostname/databasename';, and replace with the correct information for the new database. Save the file, now the new Drupal knows where the database is. Next step is to copy over the old Drupal directory's files directory, and redo any customizations done for .htaccess and robot.txt.
Point the browser to test.yoursite.com/update.php, and follow instructions to update the database. There might be some warnings, but it should be fine if there's no error. After Drupal core is upgraded. Download the third-party modules, and install them. After installing each one, don't forget to run update.php again. We again look at the running old site to see what modules are needed. Otherwise, one has to write down a long list of module names first. I still cannot believe how many modules are necessary to run a simple site like this. For fighting spams alone, I installed seven modules. Maybe it is an overkill, but it does not hurt to be on the prudent side.
Upgrading modules are easy and relatively quick. The big time sink is upgrading the theme. This site uses a sub-theme of zen. It turns out that the theming systems of Drupal 5 and 6 are quite different, so we cannot just copy the old theme over and expect it to work. All the customizations have to be redone, which means hacking the template files and the CSS files all over again. Having a working old site running is again a big help. Because the tag ids and classes are all different, it is necessary to use Firebug to track and match the styles of the two versions while hacking the CSS files.
After the new site is tested to be working properly, it is the time to bring the old site off-line and bring the new site online. All it requires is to issue a rm -rf command to delete the old Drupal directory, followed by a mv command to move the new Drupal directory to the old one, so that amounts to a couple seconds of down time. Not bad.