Development & Production Sites with Database Prefixes

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
gcassie's picture

I mentioned this at the last Boston meetup, and there was some interest so I though I would share. Running two sites off the same database and prefixing certain tables should allow for a simple dev/prod environment.

The idea is to isolate the configurations for the two different sites in two differently prefixed sets of tables, and allow all the content, users, taxonomy, etc. to mingle. To test this I've set up two subdomains, dev1.castlin.net and dev2.castlin.net. Here is the entry in settings.php for dev2 (dev1 is strikingly similar):

$db_prefix = array (
  'default' => '',
  'access' => 'dev2_',
  'authmap' => 'dev2_',
  'blocks' => 'dev2_',
  'blocks_roles' => 'dev2_',
  'boxes' => 'dev2_',
  'cache' => 'dev2_',
  'filters' => 'dev2_',
  'filter_formats' => 'dev2_',
  'flood' => 'dev2_',
  'menu' => 'dev2_',
  'node_access' => 'dev2_',
  'node_type' => 'dev2_',
  'permission' => 'dev2_',
  'role' => 'dev2_',
  'system' => 'dev2_',
  'users_roles' => 'dev2_',
  'variable' => 'dev2_',
);

Let's pretend dev1 is my production site and dev2 is my development site. I can use .htaccess to limit access to dev2 to just my IP address, then tweak it freely without worrying about disturbing the functionality of dev1. Also, I have access to all the actual content, user records, and taxonomy of my production site in real time, so I can see exactly how the changes I'm making are affecting the site.

When I get the dev site into a state I'm happy with, rolling it out to production should be easy:

  1. Put production offline for a minute.
  2. Change the prefix in production's settings.php to be the one I'm currently using for dev
  3. Clear the cache in production.
  4. Turn production back on.

After this, production and development are effectively the same site. However, if I make another copy of the unshared tables and give them a different prefix, and set dev's prefix to that new one, I've split them again. You could either switch prefixes back and forth, or use a datestamp as the prefix to get a kind of site versioning.

This approach is probably only useful for smaller sites with a single or very small pool of administrators and developers. However, I think it might be very nimble, and I really like the idea of having all the live content available in development in real time, and the potential to store "versions" of you site configuration.

Of course, there are downsides. You have to pay very close attention to how modules are changing the database, and maybe add some more prefixes. Modules that don't format their queries properly will likely break this, but that's a problem with all prefixing. It also requires a degree of discipline: any configuration changes you make in Production will be "overwritten" when you switch in the Dev prefix.

I've only tried this out on a small test site, so if you decide to use this technique on a real site, do so cautiously, and let me know how it goes!

Comments

thanks for sharing!

thomas23's picture

Thanks heaps, this was what I was looking for and have been wondering why I haven't read about it more often as it seams so "natural" for me.

Anyway, an aditional thought I'm having is to have some sort of read-only mirror of my prod site on dev.example.com whis this method or maybe even automatly updated via cron (linux cron that is). But since I'm not familiar with mysql command line I wouldn't know how to do this with bash. In theory I can even think of a backup version keeping in this very same fashion you could switch over to allmost in real time in an emergency! I'm thinking something like this: Via linux cron every few hours copy all nessesary tables from prod_prefix* to dev_prefix*. Now I can happily mugg around on dev.example.com without concern to change live data nor missing out on live content as dev tables are overwritten every other hour (I could disable the script if I need longer for a certain test). Another script I can call switch_live_prod_to_backup.sh that would change settings.php to use the (last?) backup version. This idea could optimally be extented -- kind of as you suggested -- to keep one week worth of backup prefixed tables, so you always have a "last working version".

Questions:

  1. Which tables do I need? Any other than thouse you listed above?
  2. what's the mysql command lines/queries needed?

I'd be happy to hear if someone has done this before so I don't have to reinvent the wheel. If I will (have to), however, I'll post results here.

Cheers.

P.S. If I only knew enought php I guess this would even make a nice little module with a small admin interface, wouldn't it? Or does something like this exist allready and I've missed it?

If you wanted to do

gcassie's picture

If you wanted to do something like that, I think a small module would be the way to go. You could use hook_cron and not have to worry about using bash. Then you could just disable the module if you didn't want the update to roll.

One thing you can't do in a module as far as I know is make changes to settings.php. It has to be set to read-only or you'll get configuration warnings. You might be able to change it so it has an include to a less-secure file which contains your database prefixing settings, but I'm not sure if that opens up more security concerns.

Anyway, I'm glad you like the idea!

Boston

Group categories

More Specifically

Group events

Add to calendar

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds:

Hot content this week