Уведомления

Группа в Telegram: @pythonsu

#1 Дек. 31, 2013 08:41:16

Ace
Зарегистрирован: 2012-09-05
Сообщения: 43
Репутация: +  0  -
Профиль   Отправить e-mail  

Oracle - много потоков к разным серверам

Добрый ! С наступающим !

Инструменты:
1. клиентская часть
w7 x64
Python 3-3-2 x86
fdb 1-4
cx_Oracle-5.1.2-11g.win32-py3.3.msi
драйвер Oracle ODAC v11-2021 Xcopy_32bit
2 серверные - разнообразные Oracle 10g XE, 10g Std, 11g XE, 11g Std разных битностей, но все под Вин

Общая задача: в базе Firebird лежат параметры соединений с серверами Oralce (юзер, ip и тд.). Так исторически сложилось, это обсуждать не нужно. Нужно одновременно сделать запрос на 153 сервера Oracle и снять с них некие данные - сами данные тут не интересны, вопрос в реализации многопоточности при работе с Oracle

Код

# coding: cp1251
import cx_Oracle
import fdb
import pprint
import threading
import datetime
import pythoncom
import time
res_spaces_queue=[]
ora_mutex=threading.Lock()
def get_soft_data(gissz_num,target_host):
    pythoncom.CoInitialize()
    ora_con = cx_Oracle.connect("orausr/orapass@"+target_host+"/XE")
    ora_cur = ora_con.cursor()
    ora_cur.execute("select dbms_utility.port_string, (select platform_name from v$database) ,(select version from v$instance) from dual")
    ora_mutex.acquire()
    for result in ora_cur:    
        res_spaces_queue.append([gissz_num,result[0],result[1],result[2]])
        
    ora_mutex.release()    
    ora_cur.close()
    ora_con.close()
    pythoncom.CoUninitialize()
#==========================================
#==========================================
# Main function
def main(argv=None):
    start_time=datetime.datetime.now()
    fb_conn = fdb.connect(dsn='firebird:d:\\NET_ANALISYS.FDB',user='user',password='password')
    fb_cur = fb_conn.cursor()
    SELECT=r"SELECT p.gissz_num,p.lanaddress FROM points p JOIN srv_roles s ON p.id=s.point JOIN srv_roles_types st ON st.id=s.""ROLE"" WHERE p.enabled=1 AND st.name ='ГИССЗ'"
    fb_cur.execute(SELECT)
    for row in fb_cur.fetchall():    
        t = threading.Thread(target=get_soft_data,name='id'+str(row[0]),args=(row[0],row[1],))         
        t.start()
    while threading.activeCount()>1:
        time.sleep(0.25)
    pprint.pprint(res_spaces_queue)
    
#==========================================        
if __name__ == "__main__":
    main()

Что происходит:
- при запросе SELECT=r“SELECT p.gissz_num,p.lanaddress FROM … получается краш самого питона и ошибка оракла ora-24550 , которая сводится к обращению в супорт
- если изменить запрос на SELECT=r”SELECT FIRST 10 p.gissz_num,p.lanaddress FROM …, то все отрабатывает как задумывалось. Рабочий диапазон до 12-13 единиц, от чего зависит - непонятно

Результат наводит на мысль, что есть ограничения на потоки именно со стороны DLL Oracle
Или я что-то неграмотно использую ?


И на том спасибо. Решено. На sql.ru откликнулись быстрее
http://www.sql.ru/forum/1068779/obrashhenie-k-bolshomu-kolichestvu-serverov-oracle-s-ispolzovaniem-

Отредактировано Ace (Дек. 31, 2013 14:17:47)

Офлайн

#2 Дек. 31, 2013 14:21:18

Lexander
От:
Зарегистрирован: 2008-09-19
Сообщения: 1139
Репутация: +  33  -
Профиль   Отправить e-mail  

Oracle - много потоков к разным серверам

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

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



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version