WordPress stores many options as “serialized data”, which contains both the string content of things and their length. So when you modify the URL and the length changes, then the serialized data is no longer correct, and PHP rejects it.

The longer term problem is that, basically, you’re doing it wrong. If you are setting up a development site that will have its data migrated, then it should have the exact same URL as your production site to begin with. You can manually edit your HOSTS file to give that production domain (like example.com) a different IP address (like 127.0.0.1) and thus the “production” URL will become the development site, for you only. Then you can create your data and links and everything else using that production URL, and when you migrate the data, nothing about it has to be altered.

In the short term, however, don’t use a simple text search/replace on the SQL file. As you have discovered, this breaks things.

And while I hesitate to suggest it, there is a way to alter the WordPress core code to handle these broken serializations. You have to modify the wp-includes/functions.php file, and change the maybe_unserialize() function to this:

function maybe_unserialize( $original ) {
if ( is_serialized( $original ) ) {
$fixed = preg_replace_callback(
'!(?<=^|;)s:(\d+)(?=:"(.*?)";(?:}|a:|s:|b:|i:|o:|N;))!s',
'serialize_fix_callback',
$original );
return @unserialize( $fixed );
}
return $original;
}
function serialize_fix_callback($match) { return 's:' . strlen($match[2]); }  

This is NOT a viable long term solution. It should only be used to get you up and working right now. In the long run, you need to fix your development process so that you don’t have to do this sort of URL munging to begin with.