Всегда ли операторы DDL дают вам неявный коммит или вы можете получить неявный откат? - PullRequest
15 голосов
/ 08 апреля 2009

Если вы находитесь на полпути транзакции и выполняете оператор DDL, такой как усечение таблицы, транзакция фиксируется.

Мне было интересно, всегда ли это был случай и по определению, или есть где-то скрытая настройка, которая откатывает транзакцию вместо фиксации.

Спасибо.

Изменить, чтобы уточнить ...

Я не ищу откат после усечения. Я просто хочу подтвердить, что уже выполненные заявления абсолютно всегда будут выполняться до DDL. Просто хочу убедиться, что где-то нет системного свойства, которое кто-то мог бы установить, чтобы разрушить мой код.

Я понимаю необходимость коммитить до и после DDL, но концептуально я бы подумал, что одно и то же требование согласованности можно было бы выполнить с помощью отката до DDL и коммита после.

Ответы [ 8 ]

15 голосов
/ 09 апреля 2009

Технически DDL делает коммит ДО того, как он выполнит и ПОСЛЕ того, как он выполнит.

Да, та же ссылка от Cookie, но это другой аспект той же проблемы. Важно понимать, что это не просто один коммит, а два, и они происходят как до, так и после.

15 голосов
/ 08 апреля 2009

Нет, он всегда будет фиксироваться.

Если вы хотите выполнить откат, вам придется сделать это до DDL.

Если вы хотите изолировать DDL от существующей транзакции, вам придется выполнить его в отдельной отдельной транзакции.

5 голосов
/ 09 апреля 2009

На самом деле это будет совершать, ЕСЛИ ЭТО МОЖЕТ. Если это не может успешно зафиксировать, DDL потерпит неудачу. Один из способов остановить его фиксацию - нарушить отложенное ограничение.

create table fred (id number);
alter table fred add constraint id_ck check (id >0) initially deferred;
insert into fred values (-1);
SQL> create table junk(val number);
create table junk(val number)
*
ERROR at line 1:
ORA-02091: transaction rolled back
ORA-02290: check constraint (GC_REF.ID_CK) violated
SQL> desc junk
ERROR:
ORA-04043: object junk does not exist

Так что, если вы хотите предотвратить неявное принятие, создайте фиктивную таблицу с отложенным ограничением. Вставьте в него строку нарушения, и вы можете быть уверены, что транзакция не может быть принята, пока это нарушение не будет устранено (например, строка удалена).

3 голосов
/ 08 апреля 2009

Здесь - это статья AskTom, которая может помочь. Из статьи:

"Мне было интересно, почему операторы DDL не выполняются внутри автономной транзакции (как это делают последовательности), поэтому они не влияют на ожидающую пользовательскую транзакцию ...

Вы можете уточнить?

Продолжение 24 июня 2003 г. - 7:00 США / Восточный регион:

это было бы так же "запутанно", как если бы не делать это таким образом. во всяком случае, у вас есть atrans, так что если вы хотите, вы можете. «

Так что, если вам действительно нужно, вы можете вставить свой DDL в автономную транзакцию и делать то, что вы хотите.

EDIT: Суть в том, что если вы не пойдете на явную длину, чтобы «подорвать» Oracle, DDL выполнит коммит. Тем не менее, если вам абсолютно необходимо, чтобы фиксация выполнялась в определенный момент, почему бы просто не выполнить ее явно?

3 голосов
/ 08 апреля 2009

A усеченная таблица или изменить таблицу или создать таблицу всегда вызывают фиксацию.

Почему вы хотите выполнить откат, когда выполняете усеченную таблицу?

1 голос
/ 21 марта 2012

Операторы DDL всегда выполняют автоматическую фиксацию после выполнения.

Если вы хотите выполнить откат в случае сбоя (на стороне сервера), вы можете установить определенные флаги, чтобы указать сбой, и предпринять соответствующее действие.

например: если вы создали таблицу table1. и в то же время вы вставляете запись в другую таблицу.

но вставка не удалась по определенной причине (установите флаг = true). Затем в этом случае Вы не можете выполнить откат, так как оператор create является оператором ddl, поэтому вы можете отменить изменения в базе данных, удалив таблицу (table1) в зависимости от значения флага, с помощью оператора Drop.

0 голосов
/ 13 марта 2018

«Всегда / никогда» слишком сильно. Например, DDL, такой как CREATE PRIVATE TEMPORARY TABLE из Oracle 18c, не COMMIT вашей транзакции.

Нормальный сценарий:

CREATE TABLE t(i INT);
INSERT INTO t(i) VALUES(21);

CREATE TABLE x(i INT);   -- same for CREATE GLOBAL TEMPORARY TABLE y(i INT); 
ROLLBACK;

SELECT * FROM t;
-- Output:
-- 21

Но если вы создаете личную таблицу:

CREATE TABLE t(i INT);
INSERT INTO t(i) VALUES(21);

CREATE PRIVATE TEMPORARY TABLE ORA$PTT_temp(i INT);  
-- or
CREATE PRIVATE TEMPORARY TABLE ORA$PTT_tab
AS
SELECT 1 AS c FROM dual;

ROLLBACK;
SELECT * FROM t;
-- Output:
-- no data found

ДБ <> Fiddle demo

0 голосов
/ 28 марта 2017

Я согласен с DCookie и Томом об автономной транзакции. Я собирался заявить об этом тоже.

Пример псевдокода:

Do some DML
Call autonomous function, that performs DDL
Do some more DML
rollback or commit all the DML - your choice

Хотя я не считаю это очень полезным. Если исходный DML и DDL касаются одной и той же таблицы / объекта, это не сработает. Вы получите раздор, когда попытаетесь выполнить DDL. Как и любые две транзакции, блокирующие друг друга. И если это независимые объекты, я думаю, я не понимаю, почему порядок выполнения имеет значение.

...