postawiłem sobie w miarę nowego mysql'a: Server version: 5.0.32-Debian_2-log Debian etch distribution.
zrobiłem sobie testową tabelkę:
mysql> CREATE TABLE x (id INT PRIMARY KEY); Query OK, 0 ROWS affected (0.05 sec)
sprawdzam czy dobrze się założyła, wygląda ok:
mysql> desc x; +-------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+-----+---------+-------+ | id | int(11) | NO | PRI | | | +-------+---------+------+-----+---------+-------+ 1 row in set (0.08 sec)
no to teraz pora na zabawę. wstawiam tam 1 rekord:
mysql> INSERT INTO x (id) VALUES (6); Query OK, 1 ROW affected (0.06 sec)
nadal ok. to teraz wstawiam 10 rekordów z celowym błędem:
mysql> INSERT INTO x (id) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); ERROR 1062 (23000): Duplicate entry '6' FOR KEY 1
i teraz zagadka/pytanie:
ile jest rekordów w bazie?
odpowiedź – po przerwie.
uznałbym za naturalne, że jest 1 rekord – ten z id = 1.
ponieważ myisam (domyślny engine) nie jest transakcyjny, uznałbym też, że może być 10 rekordów – w końcu taki insert to jakby 10 insertów, a fakt, że 1 padł przy braku transakcyjności jest mało istotny.
rzeczywistość?
mysql> SELECT * FROM x; +----+ | id | +----+ | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | +----+ 6 ROWS IN SET (0.00 sec)
i teraz. ja naprawdę nie czepiam się braku transakcyjności. dziwnych obejść. ale mysql właśnie zademonstrował wykonanie części polecenia. kawałka. bo tak.
😉
Śliczne 🙂
ale z tego co wiem to mysql 5 obsługuje tranzakcje
tak, ale w/g manuala (http://dev.mysql.com/doc/refman/5.1/en/ansi-diff-transactions.html)
nie dla myisam.
i teraz – ja wiem, że myisam ma swoje problemy i nie ma transakcji.
dlatego ich się nie czepiam.
czepiam się, bo w manualu jest:
The other non-transactional storage engines in MySQL Server (such as MyISAM) follow a different paradigm for data integrity called “atomic operations.” In transactional terms, MyISAM tables effectively always operate in AUTOCOMMIT=1 mode. Atomic operations often offer comparable integrity with higher performance.
co jest ogólnie bullshitem, bo jak pokazałem insert nie był atomowy!
w dyskusji z Uboottd-em stanęło na tym, że MyISAM jest atomowy, ale na poziomie pojedyńczego wiersza, zaś taki multiinsert jest przez parser traktowany jak MAKRO, którym po rozwienięciu jest karmiony backend. Przy czym uboottd się upierał, że takie zachowanie powinno być jak najbardziej przewidywalne i spodziewane dla backendu nietransakcyjnego, zaś ja – że jeśli komuś piszącemu parser i backend przyszło do głowy, że takie zachownie w ogóle może być dopuszczalne (czyli 5 insertów a nie 0 – nic nie działa – czy 9 – działają wszystkie które się udają), to istotnie ma w tej głowie nic innego jeno bullshit.
fajne 🙂
Jak na tyle lat pracy przy bazach danych to histeryzujesz. To przecież od początku istnienia tak działa 🙂 I dotyczy nie tylko INSERTów, ale UPDATE i DELETE także. Ot, nieścisłość w dokumentacji co rozumieją jako “operation” 🙂
może i histeryzuję, ale mysql’a od dawna nie używałem. słyszałem, że wiele rzeczy w nim poprawiono. w dodatku sam z siebie nigdy nie użyłem w nim składni wielo-insertów. i jest dla mnie novum, że tak to działa. bo tak jak pisałem – rozumiem, że można nie mieć transakcji, kluczy obcych itd. fine. ale nie zapewniać atomowości pojedynczej komendy?
Ale w praktyce czym miało by się różnić wykonanie jednego “wielo-insertu” od wielu niezależnych insertów w kwestii wycofywania zmian? Różnica jest chyba żadna i sprowadza się do tworzenia rejestru operacji, które w efekcie mogą, lub nie, być nałożone na dane, a to wymaga poczynienia kolejnych kroków, które coraz bardziej przybliżają do transakcyjności.
Operacje wykonywane na tabelach MyISAM odzworowywane są bezpośrednio na danych (lub pośrednio na danych poprzez cache), nie ma więc fizycznej możwliości na wycofanie czegokolwiek.
Ale marudzicie. To przecież intuicyjne. Wywalił się przy wstawianiu wartości ‘6’, więc wszystko przed się wrzuciło, a reszta już nie… 😀
Sam nie używam MYSQLa, ale jestem ciekaw jak zachowa się przy takich operacjach jak “insert into tab1 select * from tab2”, gdzie w tab2 są takie wartości jak w przytoczonym insercie. Albo, w tabeli są wartości 1,2,3,4,5,6 i ktoś wykona update: “update x set id = id + 1 where id
@Artur: w pierwszym wypadku grzecznie dopisze wybrane z tabelki tab2 elementy do tab1, w drugim dla spełniających warunek zinkrementuje id o 1.
@MySZ: nie do końca się jasno wyraziłem. Załóżmy, że w jednej instrukcji wstawiasz bądź modyfikujesz rekordy, i pod koniec przetwarzania, któryś z rekordów nie może być zapisany (np. błąd niepowtarzalności). MySQL wycofa modyfikacje, by zapewnić atomowość instrukcji?
MyISAM, czyli bez transakcji, nic nie wycofa – to co zostało wykonane to już zostanie, reszta oczywiście nie 🙂
INSERT IGNORE …. i po problemie.
@Marcin:
serio?
a to nie po prostu zignoruje błędy?