|
Страници по тази тема: 1 | 2 | 3 | 4 | (покажи всички)
Тема
|
Транзакции в MySQL 5.0
|
|
Автор |
Dakota (erotoman) |
Публикувано | 30.11.09 15:30 |
|
Добре де, по стечение на обстоятелствата ми се наложи отново да се сблъсквам челно с MySQL... ... и се натъкнах на следното нещо:
mysql> SET sql_mode = "TRADITIONAL";
Query OK, 0 rows affected (0.00 sec)
mysql> SET autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> create table test(id int primary key, name varchar(5)) engine=InnoDB;
Query OK, 0 rows affected (0.02 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test values (1, 'foo');
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values (2, 'foobar');
ERROR 1406 (22001): Data too long for column 'name' at row 1
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test;
+----+------+
| id | name |
+----+------+
| 1 | foo |
+----+------+
1 row in set (0.01 sec)
Очевидно противоречие с C-то от ACID!
Използвам версия 5.0.51a-24+lenny2, т.е. тази, която се инсталира по подразбиране с apt-get install mysql на Debian.
Из и не намерих нищо, което да покрива този случай.
"Договор, подписан с Русия, струва по-малко от хартията, върху която е написан!" - БисмаркРедактирано от Dakota на 30.11.09 15:33.
| |
Тема
|
Re: Транзакции в MySQL 5.0
[re: Dakota]
|
|
Автор |
wqw (АзСъмЖив) |
Публикувано | 01.12.09 01:36 |
|
Нямаше да се учудя дори съдържанието да беше <1, foobar>...
| |
Тема
|
Re: Транзакции в MySQL 5.0
[re: Dakota]
|
|
Автор |
salle (един такъв) |
Публикувано | 05.12.09 01:10 |
|
Няма пролем с C-то. Точно то си е напълно наред.
Явно очакваш, че при грешка се връща цялата транзакция (ROLLBACK) само, че такова изискване в стандарта няма.
Това дали да се върне цялата транзакция или само грешния оператор е оставено на усмотрението на разработчика. В случая можеш да интерпретираш този подход като частичен ROLLBACK (до контролна точка примерно)
За C-то това не е проблем. Виж за A-то може да се спори на теория.
На практика имаш избор - при грешка в отделен оператор решаваш как да продължишш - COMMIT или ROLLBACK, но вече на ниво приложение.Редактирано от salle на 05.12.09 01:12.
| |
Тема
|
Re: Транзакции в MySQL 5.0
[re: Dakota]
|
|
Автор |
Aaron (charming) |
Публикувано | 06.12.09 13:02 |
|
А ти какво очакваш да се случи при така написаните стейтменти?
Естествено, че ще имаш 1 запис в таблицата, защото имплицитно му задаваш commit;.
| |
Тема
|
Re: Транзакции в MySQL 5.0
[re: Aaron]
|
|
Автор |
salle (един такъв) |
Публикувано | 07.12.09 13:10 |
|
"Естествено, че ще имаш 1 запис в таблицата, защото имплицитно му задаваш commit;."
Глупости! Прочети пак примера на Dakota!
| |
|
За A-то става въпрос. Първоначално го открих с вторична таблица, но се оказа, че не съм бил указал правилно проверката за референтния ключ (foreign key), т.е. с консистенсито всичко е наред.
Но атомарността определено не е както трябва! Не искам никакви частични ролбеци зад гърба ми - от една транзакция искам всичко или нищо. Е и други неща искам от една транзакция, но това е друг въпрос.
Изобщо, това да проверявам състоянието на транзакцията след всяка инструкция ръчно в приложението ми звучи адски несериозно и създава напълно излишни рискове и усложнения. И то само защото СУБД-то е решило, изцяло против волята ми, че дадени инструкции (в случая - тези, които са се провалили) всъщност не са част от транзакцията (противно на това, което аз изрично съм посочил).
"Договор, подписан с Русия, струва по-малко от хартията, върху която е написан!" - БисмаркРедактирано от Dakota на 07.12.09 13:45.
| |
Тема
|
Re: така де
[re: Dakota]
|
|
Автор |
salle (един такъв) |
Публикувано | 07.12.09 14:41 |
|
Ако очакваш транзакциите да те освободят от задължението да проверяваш резултата от всеки оператор за грешки определено не си на прав път
Изобщо контролът върху изпълнението на транзакциите е най-добре да е в клиентското приложение. Особено е очевидно при "дълги" транзакции от десетки оператори когато може де се прецени доколко дадена грешка е критична и да се даде явен ROLLBACK само ако е необходимо.
Хич, не е случайно, че в Оракъл положението е същото. Там дефиницията е за неявен savepoint преди всеки оператор до който се прави ROLLBACK при грешка (което всъщност е дефиницията на SQL стандарта).
| |
Тема
|
Re: така де
[re: salle]
|
|
Автор |
wqw (АзСъмЖив) |
Публикувано | 07.12.09 15:14 |
|
И в MSSQL е така за повечето грешки, освен определени критични такива, маркирани с висок severity level.
cheers,
</wqw>
| |
Тема
|
Re: Транзакции в MySQL 5.0
[re: salle]
|
|
Автор |
Aaron (charming) |
Публикувано | 07.12.09 18:42 |
|
Е ка да са глупости!!! Не виждам нищо глупаво да съм казал.
При задаване на autocommit off означава, ше системата очаква от потребителя да commit-не или rollback-не транзакцията.
Ако има грешки със по-голям severity level и потребителя не е задал COMMIT или ROLLBACK , то database engine-а сам ще rollback-не транзакцията след определен период от време!!!
Ако обаче потребителя зададе COMMIT или ROLLBACK то следва следното:
1. Ако е COMMIT - ще влезе всичко, което не е изхвърлило грешка с опртеделен severity level, а другото няма да влезе!!!
2. Ако е задал ROLLBACK - няма да влезе нищо, дори и това, което не е изхвърлило грешка!
И само и сега не ми казвай, че говоря глупости:-)))
| |
Тема
|
Re: така де
[re: salle]
|
|
Автор |
Dakota (erotoman) |
Публикувано | 07.12.09 19:07 |
|
На кой стандарт? В , където има доста неща за транзакциите, не намирам нищо такова... или пък е описано прекалено абстрактно.
Единственото нещо, което потенциално оправдава подобно поведение е следното: "If execution of a <commit statement> is attempted, but certain exception conditions are raised, it is unknown whether or not the changes made to SQL-data or schemas by that SQL-transaction are canceled or made persistent."
Иначе не смятам, че транзакциите ме освобождават от съответното задължение, но очаквам СУБД да прави все пак нещо самичка, най-малкото да знае състоянието на собствената си транзакция, а не аз с външна логика да го определям. То е ясно, че в клиентското приложение мога да реализирам и констрейнти и тригери, че и сикуънси...
В този смисъл, предпочитам да изхождам от презумпцията, че всяка инструкция е критично важна, а не от обратната - че грешките нищо не значат. Най-малкото, това е една от основните причини изобщо да се използват транзакции - защото всички инструкции са важни и зависещи една от друга и представляват една логическа единица (операция), съответно частичният успех не е вариант. Ако пък толкова искам умишлено да изолирам част от транзакцията като не-важна, мога да го направя с изрични чек-пойнтове.
Това, което пише в Уикипедия е в същия дух.
Та, тук общо взето спорът се свежда до следното - какво точно означава командата commit?
И чия е отговорността?
За мен пускането на commit е равносилно на това да кажа на базата следното: "Виж сега, бях ти пуснал няколко команди в транзакция и искам сега да се опиташ да я завършиш успешно!"
И очаквам тя да ми отвърне: "Абе ти хубаво ми пусна команди, ама някои от тях изгърмяха, така че няма да стане твоята, защото транзакциите са нещо атомарно и не мога да завърша тази транзакция успешно, заради възникналите грешки."
А не да ми излиза с някакви женски номера от типа: "Еми аз нали ти казах и изревах, че има грешки. Ти въпреки това написа commit, значи си поел отговорност за това и си счел, че грешките не са важни."
Е не, няма такъв номер. Такъв вариант е напълно неприемлив за мен - или транзакциите са атомарни, или не са. В последния случай излиза, че не са. И дори потенциално аз да нося вината за това, пишейки commit, базата не трябва да ми позволява да го правя, защото това противоречи на самата концепция за транзакция.
"Договор, подписан с Русия, струва по-малко от хартията, върху която е написан!" - БисмаркРедактирано от Dakota на 07.12.09 19:25.
| |
|
Страници по тази тема: 1 | 2 | 3 | 4 | (покажи всички)
|
|
|