|
Тема |
Re: окей [re: wqw] |
|
Автор |
Dakota (erotoman) |
|
Публикувано | 15.12.09 14:53 |
|
|
Тук въпросът придоби две измерения.
Първото е защо изобщо използваме транзакции? Моят отговор е - сигурност. Не използвам транзакциите, заради гъвкавост, използвам ги, заради сигурността, която гарантират. И атомарността е част от тази сигурност (другите са постоянство, изолиране и трайност).
От на PostgreSQL:
We need a guarantee that if something goes wrong partway through the operation, none of the steps executed so far will take effect. Grouping the updates into a transaction gives us this guarantee. A transaction is said to be atomic: from the point of view of other transactions, it either happens completely or not at all.
Второто измерение вече е кое наистина е по-гъвкаво, а това е спорно и относително. За мен разликата на практика е, че в MySQL се прави rollback до savepoint по подразбиране и без да съм го искал. А това поведение не ми харесва и го намирам за опасно. В PostgreSQL ако искаш такова нещо, трябва изрично да посочиш, че го искаш:
db=# BEGIN;
BEGIN
db=*# INSERT INTO test VALUES (1, 'foo');
INSERT 0 1
db=*# SAVEPOINT foo;
SAVEPOINT
db=*# INSERT INTO test VALUES (2, 'foobar');
ERROR: value too long for type character varying(5)
db=!# ROLLBACK TO SAVEPOINT foo;
ROLLBACK
db=*# INSERT INTO test VALUES (3, 'bar');
INSERT 0 1
db=*# COMMIT;
COMMIT
db=# SELECT * FROM test;
id | name
----+------
1 | foo
3 | bar
(2 rows)
Има и други начини да прихванеш грешките. Да приемем, че сме направили полето id първичен ключ на таблицата test, тогава си правим помощна функция, която да обработва грешката за нарушена уникалност:
CREATE FUNCTION test_insert(test)
RETURNS boolean AS
$BODY$
BEGIN
INSERT INTO test VALUES ($1.*);
RETURN TRUE;
EXCEPTION
WHEN unique_violation THEN
RAISE NOTICE 'Insert failed!';
RETURN FALSE;
END;
$BODY$
LANGUAGE 'PLPGSQL' VOLATILE;
db=# BEGIN;
BEGIN
db=*# SELECT test_insert((1, 'foo')::test);
test_insert
-------------
t
(1 row)
db=*# SELECT test_insert((1, 'xxx')::test);
NOTICE: Insert failed!
test_insert
-------------
f
(1 row)
db=*# SELECT test_insert((3, 'bar')::test);
test_insert
-------------
t
(1 row)
db=*# COMMIT;
COMMIT
db=# SELECT * FROM test;
id | name
----+------
1 | foo
3 | bar
(2 rows)
Гъвкавостта си я има, просто, ако искаш да се прострелваш в крака, трябва изрично да си насочиш пистолета натам.
"Договор, подписан с Русия, струва по-малко от хартията, върху която е написан!" - Бисмарк
|
| |
|
|
|