Skip to content
cjhaas blog

Basically a place that Chris can post solutions to problems so he can easily find them later

cjhaas blog

Basically a place that Chris can post solutions to problems so he can easily find them later

How to move a WordPress database

Posted on May 26, 2023May 26, 2023 By [email protected]

I often see people asking how to move a WordPress database between servers, and it usually seems like they’re doing it the hard way. I move sites between domains, from PROD to dev, dev to UAT, and so on, and this is how I’ve been doing it for years, 100% fool-proof1,2,3,4.

Prerequisites

First, you need WP CLI installed, and second, you’ll need CLI access to the server. If you don’t have either, don’t bother with the rest of this. Also, if you have questions about those things, you’ll need to find a tutorial.

Second, if you think you can skip parts of this and just use phpMyAdmin, you are on your own, too.

Third, I’m going to use the terms “source server” and “destination server”. Hopefully obvious, but just to be explicit, if you want to get a copy of your live site to your local machine for development purposes, the source server is your live site, and the destination server is your local machine.

Fourth, I’m going to assume you have a hosting setup on the destination server. For local development I use Symfony’s binary but you can use whatever, XAMPP, WAMP, Docker, native Nginx/Apache. If you were moving between PROD and STAGE, I’m assuming you’ve got that already. Related to this, I’m assuming you’ve got a domain name for this environment, it will be used in this process.

Steps

Source server

  1. On the source server, cd into the site root and run wp db dump. This will give you a SQL file.
  2. Get that file to your destination server somehow. FTP, SFTP, SCP, RSYNC, RFC 1149 (make sure to implement RFC 2549, too). Place the file in the site root.
  3. Delete the file from your source server. This one’s for Bob.

Destination server

  1. On the destination server, cd into the site root and run wp db import file-2023-05-26-df8b15c.sql, replacing the file name appropriately.
  2. Run wp option get siteurl. This will give you the official site URL from WordPress’s perspective. Don’t get cocky and assume you know it. You can very easily screw up the protocol, the WWW, or something else. Only trust the result of this command.
  3. Run the following command. The first URL is the result of the previous command. The second URL is the site’s new URL.
    wp search-replace "https://production.example.com" "https://example.localhost" --recurse-objects --all-tables --dry-run
    • DO NOT include a trailing slash in either
    • READ THAT PREVIOUS NOTE AGAIN
    • Make sure to include the protocols in both steps
  4. Inspect the output of the previous command, it should tell you how many replacement would have been made. If it is zero, you are doing something wrong, stop. If it looks correct, re-run the command but remove the --dry-run parameter to update the database.
  5. Run wp cache flush

Browser

DO NOT visit the site of your destination server in your normal browser. Instead, make sure to use an incognito/private browsing window. If for whatever reason there was a problem (see additional cleanup and notes), it is possible that you will be redirected to your source server’s site, and your browser will remember this redirection. Always use a private browser first to test this. It will drive you nuts otherwise.

If you did not heed my advice, and there was a problem, and you were able to correct it, try manually going to your destination server with an extra query string in the URL, such as https://example.localhost/?a=b. The contents of the query string don’t really manner, it is just getting around the browser’s redirect cache. If that works, you are good. Links back to / will still redirect for you, however, until your browser decides to forget that. Everyone else should be fine, this is just your local browser’s redirect cache.

Additional cleanup

Let’s say your site’s canonical address is https://www.example.com. That is what you should use as the first parameter to the search-replace command. However, there’s also a very good chance that someone put content into the CMS with the non-secure protocol, so you might want to re-run the command with http://www.example.com. There’s also a good chance that someone put content in without the www, so probably run it with https://example.com, too. And… there’s also a small chance that someone used the non-secure protocol with the www, so run it with http://example.com. Sigh. When you perform these additional replacements, DO NOT change the destination URL. This step is only to fix the links in the system by canonicalizing them. This is what the full process looks like:

wp search-replace "https://www.example.com" "https://example.localhost" --recurse-objects --all-tables --dry-run 
wp search-replace "http://www.example.com" "https://example.localhost" --recurse-objects --all-tables --dry-run
wp search-replace "http://www.example.com" "https://example.localhost" --recurse-objects --all-tables --dry-run
wp search-replace "http://example.com" "https://example.localhost" --recurse-objects --all-tables --dry-run

Remember, all of my samples include the --dry-run parameter because there’s a lot of “copy and pasters” out there that don’t read, so make sure to remove those after correcting things.

The above process can also be run on your production system in order to just correct those incorrect URLs, too.

Notes

  1. Okay, maybe not 100% fool proof. Check your wp-config.php file for constants such as WP_SITEURL or WP_HOME or FORCE_SSL_*. Older tutorials used to use these and I’d really recommend removing them, but that’s a little more complicated.
  2. Also, these steps work with multisite, but extra care is needed to make sure you are addressing the appropriates tables and sites.
  3. If you were to use this process because company B bought company A, and you wanted to rename the site, this would not fix email addresses, although a similar one could be used.
  4. This process doesn’t change anything hard-coded into files. If you find just cases, fix the files, they shouldn’t be aware of their own domain usually.
WordPress WP-CLI

Post navigation

Previous post
Next post

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Recent Posts

  • Google open redirect
  • How to use AI to write code
  • Doctrine/Symfony MariaDB DSN connection string
  • Creating a portable copy of pdftotext from source
  • Gravity Forms shortcode getting extra line breaks when used with ACF

Recent Comments

  • jose luis on #2 – VB.Net iTextSharp Tutorial – Add an image to a document
  • Eliezer Castanon on iTextSharp slightly smarter text extraction strategy
  • javad on How to recompress images in a PDF using iTextSharp
  • MANOUS3784 on Flock is awesome
  • Sang on Flock is awesome

Archives

  • June 2026
  • October 2025
  • November 2023
  • September 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023
  • December 2022
  • September 2022
  • April 2022
  • October 2021
  • September 2021
  • April 2021
  • January 2021
  • October 2020
  • August 2020
  • June 2020
  • May 2020
  • December 2019
  • November 2019
  • October 2019
  • July 2019
  • May 2019
  • December 2018
  • October 2018
  • July 2018
  • November 2017
  • October 2017
  • August 2017
  • July 2017
  • June 2017
  • May 2017
  • April 2017
  • March 2017
  • February 2017
  • January 2017
  • September 2015
  • December 2014
  • November 2014
  • October 2014
  • September 2014
  • August 2014
  • July 2014
  • November 2013
  • May 2013
  • April 2013
  • March 2013
  • January 2013
  • November 2012
  • October 2012
  • July 2012
  • March 2012
  • January 2012
  • October 2011
  • September 2011
  • July 2011
  • February 2011
  • December 2010
  • November 2010
  • October 2010
  • September 2010
  • August 2010
  • June 2010
  • April 2010
  • January 2010
  • December 2009
  • November 2009
  • October 2009
  • July 2009
  • June 2009
  • May 2009
  • April 2009

Categories

  • Accessibility
  • Advanced Custom Fields
  • Authorize.Net
  • BWP Minify
  • Composer
  • Crappy Google Search Results of the Day
  • CSS
  • Doctrine
  • Drupal
  • Drush
  • Elasticsearch
  • Fun links of the day
  • Google Analytics
  • Gravity Forms
  • HHVM
  • HTML
  • iTextSharp
  • JavaScript
  • Linux
  • mysql
  • nginx
  • Optimization
  • PDF
  • PdfPTable
  • PHP
  • Plugins
  • Ramblings
  • Random things I learned
  • Redis
  • Security
  • simplesamlphp
  • SQL Server
  • SSH
  • SSL/TLS/HTTPS
  • Stack Overflow
  • SVG
  • Symfony
  • Synology
  • Uncategorized
  • Unicode
  • Varnish
  • Vendi Best Practice
  • VIP
  • Weird Google Search Results
  • Windows
  • WordPress
  • WP-CLI

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org
©2026 cjhaas blog | WordPress Theme by SuperbThemes