cx_Oracle Connection Pool — python oracle transaction

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд
Загрузка...

Вопрос:


Нужно сделать Connection Pool c использованием cx_Oracle.

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

Сначала попробовал использовать DRCP как описано тут:

http://www.oracle.com/technetwork/articles/dsl/python-091105.html

Но данные транзакции между соеднинениями не сохраняются:

В качестве проверки использую следующий код:

#coding: utf-8

import cx_Oracle

con1 = cx_Oracle.connect('user/pass:127.0.0.1:1521/XE:POOLED', cclass='test', purity=cx_Oracle.ATTR_PURITY_NEW)
cur = con1.cursor()
cur.execute('''insert into gui_view (id, name, view_type, title) values (gui_view_s.nextVal, 'TEST_VIEW', 'grid', 'VIEW_TITLE') ''')
cur1 = con1.cursor()
cur1.execute('''select id from gui_view where title = 'VIEW_TITLE' ''')
rows_all1 = cur1.fetchall()
assert len(rows_all1) > 0, 'Not Exists!'
con1.close()

con2 = cx_Oracle.connect('user/pass:127.0.0.1:1521/XE:POOLED', cclass='test1', purity=cx_Oracle.ATTR_PURITY_SELF)
cur2 = con2.cursor()
cur2.execute('''select id from gui_view where title = 'VIEW_TITLE' ''')
rows_all = cur2.fetchall()
assert len(rows_all) == 0, 'Exist!'

con3 = cx_Oracle.connect('user/pass:127.0.0.1:1521/XE:POOLED', cclass='test')
cur3 = con3.cursor()
cur3.execute('''select id from gui_view where title = 'VIEW_TITLE' ''')
rows_all3 = cur3.fetchall()
con3.close()

assert len(rows_all3) > 0, 'Not Exists!'

Третье условие не проходит.
Возможно я не правильно использую параметры и как-то можно получить одно и тоже соединение ?

Есть идея сделать отдельный процесс в котором создавать соединение и через сокет общаться с основным приложением реализовав таким образом постоянное соединение (видимо что-то наподобие sqlrelay).

Может быть уже есть какая-то легкая открытая реализация для данной задачи, чтобы не писать самому ?

Вот еще одна ссылка:

https://docs.oracle.com/cd/B28359_01/appdev.111/b28395/oci09adv.htm#LNOCI87720

Тут говорится, что соединения с сохранением состояния могут быть реализованы через connection pool, а без сохранения состояния через session pool.
То есть по идее в Oracle должна быть такая возможность.

Да и если подумать (возможно мое представление ошибочно) у сервиса базы данных запущены процессы с соедиенениями, нужно только как-то подключиться к одному и тому же.

Спасибо @Dmitry и http://www.dba-oracle.com/t_packages_dbms_xa.htm
получилось сделать такой вариант:

    #coding: utf-8

import cx_Oracle

req_start = '''
declare
  v_my_transaction  pls_integer;
  v_xa_xid     dbms_xa_xid := dbms_xa_xid(3322);
  v_xa_exception exception;
  v_ora_error pls_integer;
begin

  v_my_transaction  := dbms_xa.xa_start(
                        xid => v_xa_xid,
                        flag =>  dbms_xa.tmnoflags);

--Check if XA transaction is OK
  if v_my_transaction <> dbms_xa.xa_ok then
    v_ora_error := dbms_xa.xa_getlastoer();
    rabus_utl.debug_db('Attention! Oracle Error - ORA-' || v_ora_error || ' obtained. XA Process failed!');
    raise v_xa_exception;
  else dbms_output.put_line(a => 'XA Process ID 3322 started');
  end if;

end;
'''

req_start_continue = '''
declare
  v_my_transaction  pls_integer;
  v_xa_xid     dbms_xa_xid := dbms_xa_xid(3322);
  v_xa_exception exception;
  v_ora_error pls_integer;
begin

  v_my_transaction  := dbms_xa.xa_start(
                        xid => v_xa_xid,
                        flag =>  dbms_xa.tmresume);

--Check if XA transaction is OK
  if v_my_transaction <> dbms_xa.xa_ok then
    v_ora_error := dbms_xa.xa_getlastoer();
    rabus_utl.debug_db('Attention! Oracle Error - ORA-' || v_ora_error || ' obtained. XA Process failed!');
    raise v_xa_exception;
  else dbms_output.put_line(a => 'XA Process ID 3322 started');
  end if;

end;
'''

req_end = '''
declare
  v_my_transaction  pls_integer;
  v_xa_xid     dbms_xa_xid := dbms_xa_xid(3322);
  v_xa_exception exception;
  v_ora_error pls_integer;
begin

  v_my_transaction  := dbms_xa.xa_end(
                        xid => v_xa_xid,
                        flag =>  dbms_xa.tmsuspend);

 if v_my_transaction <> dbms_xa.xa_ok then
    v_ora_error := dbms_xa.xa_getlastoer();
   rabus_utl.debug_db('Attention! Oracle Error - ORA-' || v_ora_error || ' obtained. XA Process failed!');
    raise v_xa_exception;
   else dbms_output.put_line(a => 'XA Process ID 3322 is working!');
  end if;
end;

'''

req_end_rollback = '''
declare
  v_my_transaction  pls_integer;
  v_xa_xid     dbms_xa_xid := dbms_xa_xid(3322);
  v_xa_exception exception;
  v_ora_error pls_integer;
begin

  v_my_transaction  := dbms_xa.xa_end(
                        xid => v_xa_xid,
                        flag =>  dbms_xa.tmsuspend);

 v_my_transaction := dbms_xa.xa_rollback(
                             xid => v_xa_xid);

 if v_my_transaction <> dbms_xa.xa_ok then
    v_ora_error := dbms_xa.xa_getlastoer();
   rabus_utl.debug_db('Attention! Oracle Error - ORA-' || v_ora_error || ' obtained. XA Process failed!');
    raise v_xa_exception;
   else dbms_output.put_line(a => 'XA Process ID 3322 is working!');
  end if;
end;

'''

con1 = cx_Oracle.connect('user/pass:127.0.0.1:1521/XE:POOLED', cclass='test', purity=cx_Oracle.ATTR_PURITY_NEW)
cur = con1.cursor()
cur.execute(req_start)
cur.execute('''insert into gui_view (id, name, view_type, title) values (gui_view_s.nextVal, 'TEST_VIEW', 'grid', 'VIEW_TITLE') ''')

cur1 = con1.cursor()
cur1.execute('''select id from gui_view where title = 'VIEW_TITLE' ''')
rows_all1 = cur1.fetchall()
assert len(rows_all1) > 0, 'Not Exists!'

cur.execute(req_end)
con1.close()

con2 = cx_Oracle.connect('user/pass:127.0.0.1:1521/XE:POOLED', cclass='test1', purity=cx_Oracle.ATTR_PURITY_SELF)
cur2 = con2.cursor()
cur2.execute('''select id from gui_view where title = 'VIEW_TITLE' ''')
rows_all = cur2.fetchall()
assert len(rows_all) == 0, 'Exist!'

con3 = cx_Oracle.connect('user/pass:127.0.0.1:1521/XE:POOLED', cclass='test')
cur3 = con3.cursor()
cur3.execute(req_start_continue)
cur3.execute('''select id from gui_view where title = 'VIEW_TITLE' ''')
rows_all3 = cur3.fetchall()
cur3.execute(req_end_rollback)
con3.close()

assert len(rows_all3) > 0, 'Not Exists!'

Который работает.

Автор вопроса: Some

Источник

Вам также может быть интересно:

Drag and Drop UWP — c# xaml mvvm
Вопрос: Нужно иметь возможность добавлять изображения в приложение путем перетаскивания из файловой системы У Grid включил AllowDrop. Но как добавить перетаскиваемые изображения в коллекцию? Т.к. те ...
Растягивание Высоты , Резина — html css html5
Вопрос: Здравствуйте! Реализовал резиновый дизайн. Растягивается ширина, но длина по % не растягивается. Возможно ли это реализовать? Или так и задумано, растягивание только на ширину ...
Jquery position().left Как быть на мобильниках? — javascript jquery css
Вопрос: На мобильных устройствах, если зумишь экран, position всегда разный. $('g').position().left Как сделать так, чтобы он не менял свои значения? Автор вопроса: ...
Jquery position().left Как быть на мобильниках? — javascript jquery css
Вопрос: На мобильных устройствах, если зумишь экран, position всегда разный. $('g').position().left Как сделать так, чтобы он не менял свои значения? Автор вопроса: ...
requestAnimation и очередность отрисовки — javascript canvas
Вопрос: Здравствуйте! Реализовал 2D игру и в Edge работает все плавно и круто, но в Firefox'e подвисает, сказали, что нужно сделать, чтобы раз-два момент и все ...
Контекстное/всплывающее меню в Android — java android popup
Вопрос: Есть ли техническая возможность сделать приложение, добавляющее свое контекстное или всплывающее меню в любом месте системы? Хочу, чтобы при выделении любого текста появлялась дополнительная кнопка ...
Контекстное/всплывающее меню в Android — java android popup
Вопрос: Есть ли техническая возможность сделать приложение, добавляющее свое контекстное или всплывающее меню в любом месте системы? Хочу, чтобы при выделении любого текста появлялась дополнительная кнопка ...
Завершить службы циклом — c# windows-service
Вопрос: Можно ли остановить службы циклом? У меня есть список служб, занёс их в List List<string> name = new List<string> { "AdobeARMservice", "RemoteRegistry", "TermService", "Messenger", "SSDPSRV", ...
Завершить службы циклом — c# windows-service
Вопрос: Можно ли остановить службы циклом? У меня есть список служб, занёс их в List List<string> name = new List<string> { "AdobeARMservice", "RemoteRegistry", "TermService", "Messenger", "SSDPSRV", ...
RecyclerView — разная разметка — android recyclerview
Вопрос: Смотрел, я смотрел в сторону RecyclerView и наконец решил кинуть ListView и на тебе! В "плохом прошлом" мой ListView использовался для двух разметок. Сейчас я ...
RecyclerView — разная разметка — android recyclerview
Вопрос: Смотрел, я смотрел в сторону RecyclerView и наконец решил кинуть ListView и на тебе! В "плохом прошлом" мой ListView использовался для двух разметок. Сейчас я ...
Как правильно передать массив аргументом для пользовательской функции — php
Вопрос: Если не брать в функцию все это, тогда результат работает. А если вот так в функции все выполнять, тогда PHP ругается: «Invalid ...
Как правильно передать массив аргументом для пользовательской функции — php
Вопрос: Если не брать в функцию все это, тогда результат работает. А если вот так в функции все выполнять, тогда PHP ругается: «Invalid ...
ViewPager внутри ViewPager — такие матрешки работают? — android viewpager
Вопрос: Доброго времени суток. Назрела новая задача. Есть каталог мастеров. При выборе конкретного мастера открывается его страница (активити с ViewPager), и теперь мастеров можно перелистывать свайпом. ...
Почему id всегда 1 Yii2 — yii авторизация
Вопрос: Использую все как по документации. Для получения информации о пользователе использую $identity = $model->findOne(]); И каким бы не был email, id пользователя всегда ...

Оставьте ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *