It depends. Of course it's normally very important that your dev server is as close as possible to the production server, configuration-wise.
You could set up a test server with an identical software set to production, for the purpose of doing final testing before deploying changes.
Another option is to create a test environment on the production server itself - a private copy of the site (typically using its own database) which you can run integration testing against.
But of course, you can't run performance testing against that environment because you don't want to place unnecessary load on your production servers.
If you have more than one production server in a cluster, you could try removing one of them, upgrading it individually and testing that before you upgrade the others.
As far as production migration is concerned - we normally use a set of scripts which apply (and remove) database changes, and have a shell script which runs them as necessary. We take the production site down by setting a flag somewhere which causes users to see a "temporarily out of service" message (NB: This may or may not be acceptable depending on your customers' SLA), then run the script which applies the database changes and copies the new files into production.
We then do some cursory tests while the site is still down (the flag still lets us view the site on production), before putting it back up.
If you need your site to run with no scheduled downtime, it could be tricker.
Running a site with no scheduled downtime is pretty much impossible, as some things, especially schema changes on big tables, are bound to create problems.
If you do an ALTER TABLE on a table with 100 million rows on it, that table will become locked for quite some time, during which time PHP pages attempting to access the table will get blocked - resulting in downtime.
There is no easy way around this.
Mark