Although, these days, I generally avoid mucking around with production DBs directly. It's all manually scripted migrations, and testing said scripts on a backup or unused slave, which is by far the safest, and also helps to avoid running queries that might adversely affect production's performance.
1: http://dev.mysql.com/doc/refman/5.7/en/mysql-command-options...
My command in the buffer might go through these steps:
1. "Delete from" 2. "-- delete from" 3. "-- delete from table where condition limit n;" 4. (Generally either ask a co-worker or make a Jira with the exact command I have at this point, so there's a sanity check and/or permanent record, but for very low risk/especially mundane/especially time critical updates, do it) 5. Delete the "--" and run it. 6. Think hard about adding some functionality in the app for doing it in app code unsteady of in database code.
Generally do the same for "UPDATE".
Another trick it to start all "DELETE" commands as a "SELECT" to ensure you get the "WHERE" part correct, and then swap out the "SELECT *" with a "DELETE".
This is an alternate form of the flag --safe-updates, this option prevents MySQL from performing update operations unless a key constraint in the WHERE clause and / or a LIMIT clause are provided.
When this isn't possible, I do a select for the PK and delete based upon only the PK. This way I can review the rows to be deleted and back them up manually if needed.
All of this is way overkill considering the backups available these days.
abort;
begin;
Just to be doubly sure. Then notice the number of deleted rows, and select from the table afterwards.
Transactions are a sane safeguard if you absolutely must run SQL on your production database.
The less manual steps the less mistakes will happen.
Start your .sql file with "use xxxxx" (non-existent database name; will prevent execution if you fat-finger F5.) Always write your deletes as a SELECT first:
SELECT *
-- delete
FROM blah
WHERE blah = 1
Never uncomment the "delete" line; just select the portion of the query after the comment with your mouse and F5 it.
And of course: always design your database with support for soft-deletes, because sooner or later you'll need to add them in.
BEGIN TRAN
DELETE (without where clause)
UUPS!
ROLLBACK
That said it would be not quite honest that there wasn't an incident in my past, which enforces this policy. Always! Without fail! BEGIN TRAN; DELETE (without where clause)
... on the same line.I've lost a lot of data to "oh lets find that line in mysql history... up, up, enter, FUCK"
A few hours later we had got a few calls from angry customers who couldn't log in. I had effectively forgotten the WHERE clause so all users had the same password: mine.
Extra points for not having read the "xxx rows updated" line that the mysql console outputs after each query...