How I destroyed the company's DB (a stupid SQL mistake)
zaidesanton.substack.com
zaidesanton.substack.com
This is weird. SQL has ; as a command separator, why treat empty lines specially?
This is a bizarre client implementation.
I use blank lines to separate sections of long queries all the time for readability and have never had a problem with any tool ever.
There is a setting called 'Blank line is a statement delimiter' which is on by default for some reason
You can't safely use semicolons as delimeters unless you parse/tokenize the entire statement (to exclude quoted semicolons). The exact handling of quoted string literals can vary depending on the SQL dialect, or even the configuration, and getting it wrong could cause even more unpredictable behavior.
For instance, on MySQL I don't think it's possible to reliably identify statement boundaries without knowing the server-side value of the NO_BACKSLASH_ESCAPES setting.
Making newlines significant by default is... well, yeah. OP should beat themselves up a little bit less.
If you wrote `DELIMITER \n` in SQL (if it was allowed) it would be a total shitshow.
select * from foo
select * from bar
update foo set val=1
will trigger to select statements and do an update.So I generated an argon2 hash, manually loggin to db to set it. I want to run:
``` update users set hash = 'hash' where email = 'cbo email'; ```
Unfortunately, the `;` character was used as part of the hash so during copy and paste the whole thing become:
``` update users set hash = 'hash'; where email = 'cbo email'; ```
It ran immediately and reset password for all of our users.
I had to make a new db from the point in time recovery to copy password back.
always use transaction and commit the result will be the way from now on.
Scary moments
Working in databases is like an old adage I heard from an aged motorcycle cop. There are two types of motorcycle riders. Those that have been in an accident, and those that will be.
For something like this, LIMIT 3 if you assume the query is correct (e.g. in production), or LIMIT 4 if you're running it manually -- so that if it reports 4 rows changed instead of 3, you know you messed up somewhere, but at least you only have up to 4 rows to fix by hand, rather than an entire table.
Still, it would probably have been after the where, and ignored too.
not using transactions is probably my biggest mistake here.
The issue wasn’t the statement, it was the tool thinking blank line == end ststement.
If you broke in on Oracle, where you must explicitly commit statements (unless your client sets up auto-commit), this can take some getting used to.
Disable the flag if you want pure SQL. And just use "WHERE true" otherwise.
UPDATE orders
SET is_deleted = true
DELETE without WHERE wasn't part of the problem.- ALWAYS do the work inside of a transaction, as he mentioned. Rollback is your friend. For final run I always do a rollback and "clean" run just to make sure nothing extra slips in.
- Start by crafting your delete/updates as SELECTS. Make sure it targets the data you want then save the SELECT to run afterwards.
- Export any data you plan to modify off to a spreadsheet and save it somewhere. This is another chance to check it's what you intended to change, it's a record of what was changed, and it can be used to revert the data if needed.
- As the author mentioned, get another pair of eyes if possible. Besides making it less likely for things to go wrong, people are more understanding.
- And it probably goes without saying, but don't just fix the data and move on. Do everything possible to track down the bug that caused the issue in the first place and fix it. This is another place where having previous data available in a spreadsheet (or even a complete database backup) can help with data mining after the fact.
If you wanted to commit, or it found an INSERT, UPDATE, or DELETE in the command, it would ask for a password plus a nonce emailed to you that you needed to enter. Sure, I didn’t get the full IDE support of a proper workbench, but that had the side effect of making me write/test commands elsewhere.
Actually, making it require two personal passwords like missile keys on a submarine would have been a cool idea. Anyways, we used it for about 11 years and it saved us a lot of trouble.
There's a part of one of the Netflix DevOps books about how only the really senior, really important staff screw up the most. It generally takes access, ability, and doing challenging things that the most senior and impactful staff are trying to accomplish to end up in a position where a mistake will cause big damage. That said, yes, teams should also build and deploy resilient systems with well practiced back-ups and restores, and make that common place enough that everyone can restore quickly.
I think in my case the closest to this was a very similar case - fixing a customer record in the customer DB. I'd written the sql quickly, was in a GUI SQL client, and far too fast selected the query from the many I was working on, and hit the shortcut to run it. Then realized a split second later I'd mis-selected just the UPDATE and SET statements, and missed the WHERE. Every customer was name called John Smith. Whoops.
I know he called out that he's in a start-up, but in my case I was at a big financial. The other lesson I learnt is to make very good friends with the infra teams, and have sufficient mutual respect and support that you (as front-office) do as they ask, and go out of your way to help with whatever projects they have (eg. upgrades, patching, migrations), and at the same time, don't bother them will silly questions, and in return be clear that when you do need something and say it's urgent, that it's genuinely urgent and needs immediate attention so that DB restores get handled ASAP. Be a great customer to them, and they'll be great service providers back.
I really think everyone in IT should be familiar with it and keep it in mind when designing systems.
I also configure databases to be "Production" within DBeaver, which adds a few extra "Are you sure checks?" so that might be why I see the message.
ref: https://dba.stackexchange.com/questions/223425/how-to-test-q...
Due to some bug, there were duplicate missions created, and it messed up the systems and confusing the operations team.
This lead to some errors when we tried to get data for these checkout items and got back that they weren't found.
Do that enough times and eventually someone will forget to edit the order, and at the front of the queue you'll find an order for nothing. Which downstream systems will quite reasonably not accept, as it's obviously corrupt.
Accidental operations can be avoided with data access governance tools.
I mean, you didn't really delete the orders... does anyone DELETE things now a days?
UPDATE orders SET deletion_timestamp = CURRENT_TIMESTAMP() WHERE deletion_timestamp IS NULL
Yes. OLTPs work best when cold data is hard deleted from the hot instances. Backups and OLAP can keep things for longer, as needed. GDPR, right to be forgotten, and similar regulations may require deleting even scrubbed copies. (IANAL)