Версия Postgres:
PostgreSQL 11.0 для x86_64-pc-linux-gnu,
, скомпилированная gcc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9), 64-разрядная
У меня есть эта хранимая процедура, как показано ниже.Это просто тест.В этой процедуре у меня есть 2 транзакции:
Первая должна завершиться нормально (т. Е. Я написал код, чтобы он не сталкивался с какими-либо ошибками, и поэтому он достигнет COMMIT
заявление).
Предполагается, что вторая транзакция завершится неудачей, поскольку я намеренно ввел в нее ошибку (либо через этот cast
там, либо через INSERT
, который вызывает нарушение PK).
Кроме того, yb.print_now
- это простая функция, которая просто регистрирует (вставляет) сообщения в другую таблицу.
Когда я запускаю эту хранимую процедуру, я ожидаю, что обновления и регистрация сообщений, выполненных первой транзакцией, сохранятся в базе данных, даже несмотря на то, что вторая транзакция завершилась неудачно.
Но этого не происходит, кажется, что обе транзакции откатываются.
- Почему это?Я делаю что-то неправильно?
И еще 2 вопроса, которые очень важны для меня.:
Когда происходит ошибка (скажем, как в строке, помеченной ***
) и когда управление достигает / переходит к блоку EXCEPTION
, у меня возникает ощущение, что транзакция, в которой я находился, уже откатывается, прежде чем я дажедобраться до блока EXCEPTION
.Поэтому в блоке исключений я не могу сделать ROLLBACK
или COMMIT
или что-либо, связанное с транзакцией.Это чувство правильно?
Скажите, что я хочу зафиксировать все, что сделано, несмотря на ошибку, есть ли способ, которым я могу это сделать?
Это именно то, что я хочу здесь.Ошибка - это ошибка ... Хорошо, но я хочу, чтобы все, что произошло до того, как я получил ошибку, было зафиксировано.
Как мне это сделать в Postgres 11?
CREATE OR REPLACE PROCEDURE yb.test123()
LANGUAGE plpgsql
AS $procedure$
DECLARE
var_cnt int;
c int;
BEGIN
START TRANSACTION; --- 1 ---
raise notice '001.';
PERFORM yb.print_now('===> 0010.');
var_cnt = 0;
update yb.mbb
set the_price = the_price + 1
where
the_id = 23164;
raise notice '002.';
PERFORM yb.print_now('===> 0020.');
raise notice '003.';
PERFORM yb.print_now('===> 0030.');
update yb.mbb
set the_price = the_price + 1
where
the_id = 23164;
COMMIT; --- 1 ---
START TRANSACTION; --- 2 ---
c = cast('###a1e3Z' as int); --- *** ---
raise notice '004.';
PERFORM yb.print_now('===> 0040.');
update yb.mbb
set the_price = the_price + 1
where
the_id = 23164;
-- insert into yb.mbb(the_id)
-- values (23164); -- this will throw duplicate PK error
raise notice '005.';
PERFORM yb.print_now('===> 0050.');
COMMIT; --- 2 ---
EXCEPTION
WHEN OTHERS THEN
raise notice 'We are in the exception block now.';
-- ROLLBACK;
-- COMMIT;
RETURN;
END
$procedure$;