Pitanje za milion dolara u nekom popularnom kvizu. Imate samo 15 sekundi za odgovor. Srecni ste jer ste izvukli pitanje iz vase omiljene oblasti 🙂
Kako obrisati sve korisnike ciji nick pocinje sa donjom crtom (‘_’).
I vas odgovor je naravno:
delete from users where username like '_%';
Vec mastate o raskalasnom zivotu daleko od kompjutera, mozda i neka jahtica pride (i sve sto ide u to lol). Glas voditelja vraca vas u surovu realnost. “Zao mi je, ovo nije tacan odgovor”. U neverici gledate vas query i milione koji su otisli u nepovrat.
Verovali ili ne, slicnu nevericu iskusio sam na svojoj kozi pre nekoliko veceri, tacnije 8. aprila. U tabeli sa nekoliko miliona generisanih domena uocen je bug (mala greska u regularnom izrazu) i nekako su generisani i domeni koji pocinju sa znakom “_”. Underscore (donja crta) naravno nije dozvoljen kod domena, bug je ispravljen ali treba obrisati i te nevalidne domene iz baze. Nista lakse, jedan brzi query i sve ce ubrzo biti pocisceno. Otvaram mysql klijent i bez mnogo razmisljanja kucam:
mysql> delete from result_domains where domain like '_%'; Query OK, 9035782 rows affected (9 min 57.35 sec)
WTF!?? Query je obrisao sve domene iz tabele. Ali kaaakooo???
I onda se setim. Donja crta – ‘_’ je poput ‘%’, takodje joker karakter koji za razliku od ‘%’ (koji menja ‘nula ili vise’ karaktera), ‘_’ menja tacno jedan karakter. Ne secam se kada sam ga poslednji put koristio (ako sam ga uopste koristio), ali znam da mi je on dosao glave.
Cimam admina na ICQ … treba mi backup, server taj i taj, tabela ta i ta, poslednji koji imamo … ASAP! Posle 30-tak sekundi admin se javlja “ok, poslednji koji imamo je od 8 marta. Gde da ti stavim?”. FUCK!!!
FUCK!!! FUCK!!! FUCK!!! FUUUUCK!!!
Ustajem od kompjutera i besno setam kroz sobu. Na postoji nacin da objasnim klijentu da sam jednim jedinim kverijem sjebao sate i sate mukotrpnog rada, podatke vredne verovatno hiljade dolara. Da imam utoku verovatno bih pao u iskusenje da pucam sebi u glavu. Mozda pre toga da sredim i admina? Kako god, sta je tu je, ne preostaje nista drugo nego da napisem email i objasnim svom klijentu sta se desilo.
Sedam ponovo za comp, ali umesto da otvorim thunderbird, cimam ponovo admina.
– Ja: “Jebote … kako se desilo da je poslednji backup star mesec dana???”
– Admin: “Kako to mislis? Ovo je backup od sinoc!?”
– Ja: “Rekao si 8 mart???”
– Admin: “Ups. Sorry, 8. April. Sad gledam, kreiran je pre samo par sati. Moze?”
I tako, my ass has been saved. Ali moglo je i biti drugacije. Mnogo drugacije.
Pouka price:
1) Budite ekstremno oprezni kada kucate nesto unutar mysql klijenta (ili phpmyadmina) koji barata sa live podacima
2) Ako morate da brisete/update-ujete nesto, uvek uradite prvo count nad istim podacima i istom where klauzom kako bi ste se uverili da je to bas ono sto ste zeleli.
Npr:
mysql> select count(*) from result_domains where domain like '_%'; +----------+ | count(*) | +----------+ | 9035782 | +----------+ 1 row in set (5.27 sec)
(ups nesto ne valja, ovo ce obrisati sve domene koje imamo)
mysql> select count(*) from result_domains where domain like '\_%'; +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (4.18 sec)
Aha, sada je sve ok 🙂
3) Uvek pravite redovan backup. Ako to za vas rade admini postarajte se da rade svoj posao kako treba. Cak i tada nije losa ideja da s vremena na vreme napravite sopstveni backup.
P.S. Problem sa pocetka price (matchovanje stringa koji pocinje sa ‘_’) resava se jednostavnim escapovanjem specijalnog karaktera. Dakle:
select foo from footable where somefield like '\_%';
ili ako ste ljubitelj regularnih izraza:
select foo from footable where somefield regexp '^_';