Ben gives some good practical updating advice.
And I agree with him that for the majority of cases, the best practice is to update locally, then push to production.
Just adding my 2 cents on top of that.
First, some background:
Being a self-hosted PHP web application is a hard life. Your parents try to raise you correctly and equip you with the tools necessary to successfully go out into the world and live on some stranger's unknown, unfriendly and oftentimes hostile server environment so you can serve up web pages, but things are stacked against you.
For any given 1,000 web hosting providers, you will find 2,500 different environmental configurations... at least. Different Linux distributions each with their own different libraries and versions. Windows servers running IIS... or Apache. Different permissions and user/group setups for each account. Different versions of Apache and all of its modules... or nginx. Different MySQL versions each with different configurations. Or "drop in" MySQL replacements that the host doesn't mention they're using, that's actually not a drop in replacement. Or hosts that decide it's a good idea to store PHP sessions in memcached.
You'll find yourself living on fully-managed servers where you have limited to zero control of what you can do. On boxes administered by weekend sysadmin warriors, running the bleeding edge of every piece of software on their box, because they read it on HackerNews. You'll live on overloaded, underperforming, $5/month shared hosting accounts where the host has crammed 400 sites on one box and you get blamed for being slow.
Everything is broken. It's amazing software works at all, much less the Internet.
How is a simple PHP script meant to survive is such as harsh world?!
Now that we've painted this picture of a horrible, bleak universe that Craft has to live in, let's look at some stats:
- Craft has successfully sent out over 8,100 auto-update requests.
- 94% of Craft installs with recent control panel usage are running Craft 2.
- Since launch, we've received roughly 2,000 Craft-related support tickets.
- About 370 of those tickets have been related to updating.
Soft, touchy-feely, by-the-gut numbers:
Of those 370 updating support tickets, I'd guess 90% of them fall into environmental issues that are mostly outside of Craft's control, but Craft tries to deal with as gracefully as possible.
Usually the culprits are either a) permissions aren't setup correctly and Craft can't download the update patch file, unzip it, or write to the craft/app folder to actually update the files b) during the update, Craft runs into a php.ini limitation... memory_limit and max_execution_time being the most common.
Both of these can be an issue if they are set low (32M and 30 seconds on older PHP installs or stingy hosts), or the size of your database has grown large enough that when Craft tries to automatically back it up during an update, it bumps into them. That's a reason we added the backupDbonUpdate config setting.
We'll also see a spike in update errors related to these settings during bigger Craft updates (like 1.3 => 2.0) when we'll do an update to Yii, for example, that touches thousands of files. More files in an update = more time to process the update = more of a chance of bumping into a limit. Some people might prefer to do a manual update during those times, since that can finish executing quicker than an auto-update would.
Craft will also try to increase these limits for itself at runtime during potentially long running or memory intensive operations like updating, but that doesn't always work. Some hosts have hard limits on them and things like FastCGI don't allow PHP scripts to use ini_set() in order to increase them at runtime.
5% of those tickets are related to bugs in a database migration that the update needs to run. This usually occurs when we overlook some way that someone is using Craft and usually get fixed quickly.
The remaining 5% of the tickets were related to bugs in the updating logic in Craft itself. We saw a few of these back in the 1.0, 1.1 and maybe 1.2 days, but honestly haven't ran into one in quite awhile (knocks on wood).
Does Craft practice safe-updating?
I think so. We've got some ideas to try and further bullet-proof the process, but this is how it stands currently and is working out pretty well.
When Craft downloads an update patch file, it first validates the MD5 hash of the file to make sure that the file it received is the one it expected and nothing got corrupted during the transfer. If a failure occurs here, we consider that a non-rollback failure - meaning, a failure has occurred, but no files have been updated, the database hasn't been touched and the site is still online - so no harm, no foul.
Craft will unzip that file to a temp location, grab the
RequirementsChecker script from the recently unzipped file and run it, so that if any new requirements were added to be able to run Craft, and your server doesn't support them, you'll get a message stating so. If a failure occurs here, it's a non-rollback failure.
From the recently unzipped patch file, Craft will validate that all of the paths that it's about to update are still writable by PHP. If a failure occurs here, it's a non-rollback failure.
Craft will now make a backup of all of the files/folders it's about to update by coping them from
folderName.bak. If the update deleted a file/folder, it still gets a backup created. If a failure occurs here, it's a non-rollback failure.
The recently updated files get coped over to their new homes. If a file was deleted during the update, it gets deleted at this point. If a failure occurs here, it's a file-only rollback failure and Craft will attempt to take all of the recently backed-up .bak files and put them back in their proper place and put the site back online. The database hasn't been touched at this point.
If Craft is configured to backup the database during update, this is the point where a database backup gets created. If a failure occurs here, it will do a file-only rollback.
If the update came with any new database migrations (alter table schema, and/or data) to run, this is the point where they run. If a migration fails, or any other error occurs, this is a full-rollback failure and Craft will attempt to restore the database from the backup it just made in step 6 to its last known working state, as well as perform the file rollback.
If we've made it this far, we're almost done. All that is left is housekeeping. Craft will try to delete all of the .bak files it created as well as flush various bits of info from cache. If a failure occurs at this point, technically the upgrade is finished, so we don't attempt any rollback.