6104 comments
2357 subscribers
6264 on Twitter
Subscribe! Feed reader E-mail

Drupal 5: Migrating a production database to a QA server

Building on the configuration management strategy I described last time, I wrote some scripts to make it easier for other developers to migrate the production database to the QA server or to get a copy of the production database for their local system. I needed to consider the following factors:

  • Domain name changes: Because we use Domain Access to serve multiple subdomains using a single Drupal installation and shared sign-on, we needed to make sure that all instances of the domain root are replaced and the correct domain_root is set. For example, the site URLs might be:
    Production QA Local
    example.com qa.example.com local.example.com
    foo.example.com foo.qa.example.com foo.local.example.com
    bar.example.com bar.qa.example.com bar.local.example.com
  • Privacy concerns: The QA database and local copies of the database should not contain sensitive user information. All users aside from the administrator should be removed from the system, and all content on site should be limited to editorial content.
  • Efficiency: We don’t need data like access logs or watchdog logs in QA or for local testing. This saves quite a lot of time and space during the data migration process.

Here’s how I did it:

  1. I identified tables I needed to copy over and tables that I could just leave empty. I did this by going through the output of “SHOW TABLES” in a MySQL console.
  2. In my Makefile, I declared a DB_DATA variable that contained a list of tables I wanted to copy.
  3. I wrote a backup_partial target in my Makefile that issued a series of commands:
    mysqldump -u ${DB_USER} --password=${DB_PASSWORD} ${DB} --no-data > partial.dump  # export the schema
    mysqldump -u ${DB_USER} --password=${DB_PASSWORD} ${DB} --opt --complete-insert ${DB_DATA} >> partial.dump # Dump some of the data
    mysqldump -u ${DB_USER} --password=${DB_PASSWORD} ${DB} --opt --complete-insert --where='uid< =1' users users_roles >> partial.dump # Dump the admin and anonymous users
    echo "UPDATE node SET uid=1;" >> partial.dump # Set all the node authors to admin
    echo "REPLACE INTO search_index_queue (nid, module, timestamp)  select nid, type, unix_timestamp(now()) FROM node;" >> partial.dump # Prepare for reindexing
    
  4. I wrote a shell script on an internal server that accepted an argument (the domain to translate to) and performed the following steps:
    1. ssh into the production server and run make with my backup_partial target, compressing the resulting partial.dump
    2. scp the partial.dump.gz from the production server onto the internal server
    3. unpack partial.dump.gz
    4. figure out what $DOMAIN is supposed to be based on the arguments
    5. run perl -pi -e "s/example.com/$DOMAIN/" partial.dump
    6. load partial.dump into my database
    7. run cron.php if it can
  5. I added two buttons to my web-based deploy script: one button to migrate the production database to the QA server, one button to make a copy of the production database for the domain “local.example.com”. Both buttons call
  6. I created multisite settings.php in my Drupal directory (ex: sites/local.example.com and sites/qa.example.com). The production settings go in default/settings.php, and the multisite settings.php override it like this:
    $conf = array(
      'domain_root' => 'local.example.com',
    );
    $cookie_domain = '.' . $conf['domain_root'];
    

    $conf allows you to override Drupal variables returned by variable_get.

So now, I can click on a button to migrate a sanitized copy of the production database to the QA server or to my local system. Sweet!

Short URL: http://sachachua.com/blog/p/5059
  • http://davenjudy.org/wordpress Dave Miller

    Nice description. Any chance you would like to share the table list (DB_DATA)?

    I’m currently migrating my blog and web site to Drupal. The web site is really lame but I was hand coding HTML. Decided I needed something classier that would allow me to still provide my blog content but integrate it with the rest of the web site. Thus, Drupal.

    I’d like to keep my Drupal learning and experimenting activities confined to my internal, development server and just have “finished product” on the external server. So I’m very much in the position of needing something like the capabilities you described in this post.

    Cheers,
    Dave

On This Day...

  • 2012: Learning more about Android development — From Tuesday: I spent most of the long weekend learning about Android development by working on the MobileOrg for Android [...]
  • 2011: Drupal: Overriding Drupal autocompletion to pass more parameters — Drupal autocompletion is easy – just add #autocomplete_path to a Form API element, set it to something that returns a [...]
  • 2010: Monthly review: July 2010 — Last month, I said: What will July be like? I want to polish my community toolkit and share it with more [...]
  • 2009: Improv: Catch 23′s Next Act, people-watching — Hat-tip to Taylor for telling me about Catch 23‘s improv event at the Comedy Bar last night. It was a [...]
  • 2009: The sweetness of life — W- and I made apricot syrup. It’s amazing. I’m tempted to go and make pancakes right now. I’m sure they’re fine for [...]
  • 2008: Deploying to servers — I’m heading to the Philippines tomorrow, and to make life easer for the two other Windows-based PHP developers on my [...]
  • 2007: I survived my defense! — zomg, I’m actually done with the defense. I need to make a few minor revisions, but the bulk of my work [...]
  • 2006: Raided the library — Having discovered the joys of the online book request system, I raided the library for 22 books on various topics including [...]
  • 2006: Time bubble — For some reason or another, my initial “Wow, this has been quite an eventful year” reflection included my stay in Japan. [...]
  • 2005: My Web 2.0 – Yahoo’s social search — Yahoo’s social search engine, My Web 2.0, certainly looks promising. It automatically picks up your Yahoo Messenger contacts and prioritizes their (and [...]
  • 2004: del.icio.us: sachac — http://del.icio.us/sachac: My del.icio.us page. New URLs will be posted there instead of on this blog, because blogging to del.icio.us is slightly more [...]
  • 2004: Myrkraverk’s box — -----BEGIN PGP MESSAGE----- Version: GnuPG v1.2.4 (GNU/Linux) hQEOAzQ6c9jHW5SMEAP/S9ch+peMGLyEn7Cmu0PdVIu3QW7XP75BJDypzQRzhOOh OwONxwtnH3yzkOfrwNxzQVPb5fyfWQgOjtlLZdPeDAxV8uBvj3ysmUwFH0SVSaKX O/wR0mr801hW1kbLR073+J8+Xvz5ioLb+3B1Kt1knaZ1U51XGxTieCaEQ3rpx94E AImExgp+j8Neuv40itenuroVSmM3uFAx1yCvlbc1pDAJOJp//X7AFRPsxwXxFidW rDHojDShCqGzy9CCQ10QfLdc1AswQIf1EP4V+BfYWp4Cg1byoBvjw0+2VEmuW196 rUh+8FyDUaigarCB64/M1fW6E2+0vNZ8SvG8bB77Z6MQ0mEBcuESqr1lrTDACIzs pGGuixg3TRzVflhH0Cf9jwid8je28gOqDUiGAhg/MGFQnroSpGfBVy/tqE227eRP mh6qnBpq9fBr0TcHPAhqjhghlmj7jP0WWl7i+LFZpAvhRRHc =c0jl -----END PGP MESSAGE-----
  • 2004: AOTS confirmed — Incidentally, I really _am_ going on the industry training trip to Japan. I’ll be leaving on August 25.

Get the highlights as a PDF!

Stories from my Twenties: Highlights from a Decade of Blogging

Free sample!