Почему я получаю открытую транзакцию, когда просто выбираю из базы данных View? - PullRequest
8 голосов
/ 20 декабря 2010

Если я выполню простой оператор выбора в pl / sql developer для таблицы базы данных, я получу стандартный набор результатов обратно, как и ожидалось.

Недавно я вставил запрос из хранимой процедуры, которая случайно выбрала вид, и заметил, что транзакция, по-видимому, оставлена ​​открытой. Это было выполнено с помощью отката, и параметры фиксации были доступны в PL / SQL-разработчике.

Опрос других разработчиков показал, что это влияет на некоторых, но не на других, что заставляет меня подозревать настройки PL / SQL Developer.

С какой стати это так? В представлении itelf есть DBLink для другой базы данных, но я не ожидаю, что это окажет какое-либо влияние.

Есть мысли?

Ответы [ 5 ]

18 голосов
/ 20 декабря 2010

Вопреки вашим ожиданиям, похоже, что ссылка на базу данных является источником открытой транзакции.Я заметил такое поведение раньше при выполнении запросов SELECT для удаленных таблиц в PL / SQL Developer.

Цитируя Тома Кайта ( source ):

распределенный материал запускает транзакцию «на всякий случай».

EDIT : «Любой оператор SQL запускает транзакцию в Oracle»?Нет, это не так, и вот демонстрация этого.В этой демонстрации используется представление словаря данных V $ TRANSACTION , в котором перечислены активные транзакции.Все это выполняется в моей локальной базе данных Oracle XE, к которой не подключены никакие пользователи, кроме меня.

Мы будем использовать следующую таблицу во время этой демонстрации.Он содержит только один столбец:

SQL> desc test;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 A                                                  NUMBER(38)

SQL> select count(*) from v$transaction;

  COUNT(1)
----------
         0

На данный момент нет активных транзакций.Давайте запустим SQL-запрос к этой таблице:

SQL> select * from test;

         A
----------
         2

SQL> select count(*) from v$transaction;

  COUNT(1)
----------
         0

Все еще нет активных транзакций.Теперь давайте сделаем что-нибудь, что запустит транзакцию:

SQL> insert into test values (1);

1 row created.

SQL> select count(*) from v$transaction;

  COUNT(1)
----------
         1

Как и ожидалось, теперь у нас есть активная транзакция.

SQL> commit;

Commit complete.

SQL> select count(*) from v$transaction;

  COUNT(1)
----------
         0

После фиксации транзакции она больше не активна.

Теперь давайте создадим ссылку на базу данных.Я использую Oracle XE, и следующее создает ссылку на базу данных из моего экземпляра Oracle XE обратно на себя:

SQL> create database link loopback_xe connect to user identified by password using 'XE';

Database link created.

Теперь давайте посмотрим, что происходит, когда мы выбираем из таблицы ссылку на базу данных:

SQL> select count(*) from v$transaction;

  COUNT(1)
----------
         0

SQL> select * from test@loopback_xe;

         A
----------
         2
         1

SQL> select count(*) from v$transaction;

  COUNT(1)
----------
         1

Как вы можете видеть, простой выбор из удаленной таблицы открывает транзакцию.

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

3 голосов
/ 20 декабря 2010

Любой Оператор SQL запускает транзакцию в Oracle.

Из руководства:

Транзакция начинается с первого исполняемого оператора SQL. Транзакция завершается, когда она фиксируется или откатывается либо явно с помощью оператора COMMIT или ROLLBACK, либо неявно, когда выполняется оператор DDL. [...] исполняемый файл Оператор SQL - это оператор SQL, который генерирует обращения к экземпляру, включая операторы DML и DDL

Скорее всего, те, кто этого не видит, работают в режиме автоматической фиксации, когда транзакция, начатая оператором, сразу же завершается после того, как оператор завершен.

Другие утверждали, что SELECT не является DML, но опять же в руководстве четко говорится :

Операторы языка манипулирования данными (DML) запрашивают или манипулируют данными в существующих объектах схемы. Они позволяют вам:

* Получить или извлечь данные из одной или нескольких таблиц или представлений (SELECT)
* Добавить новые строки данных в таблицу или представление (INSERT)
[...]
1 голос
/ 20 января 2015

Обратите внимание, согласно Руководству администратора Oracle 11g , если вы выполните простой старый SELECT по ссылке на базу данных, вы начнете транзакцию, которую необходимо зафиксировать (или откатить).

1 голос
/ 04 апреля 2012

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

"Транзакция в базе данных Oracle начинается, когда первый исполняемый SQL Заявление встречается. Исполняемый оператор SQL является SQL оператор, который генерирует вызовы к экземпляру, включая DML и DDL заявления. "

SELECT не является ни DML, ни DDL. Это также ТРУДНО, чтобы действительно проверить это. Я не хочу показаться здесь троллем, но это действительно раздражает, когда люди просто выкидывают ответы на форуме, чтобы попытаться получить очки, а ответы - полная чушь.

Прочитайте остальную часть документа и ПРОВЕРЬТЕ ЕГО ПЕРВЫЙ.

  • вход в сеанс
  • запустить выбор
  • проверьте, есть ли у вас открытая транзакция, присоединив v$Session (для вашего сеанса) к v$transaction.

Если запись возвращается, у вас есть транзакция. Если нет, то нет.

0 голосов
/ 20 февраля 2019

Select является частью только DML, но блокировка не получена. Блокировка строки извлекается при вставке / обновлении / удалении / выборе для обновления.-Росс верен.

https://docs.oracle.com/cd/E11882_01/server.112/e41084/ap_locks001.htm#SQLRF55502

                        ROW Lock    Table lock

SELECT ... FROM table ... ----- Нет

INSERT INTO table ...Да SX

То же самое с удалением обновления и выбором обновления.

...