Я пытаюсь выбрать данные из базы данных ORACLE 12c с помощью cx_Oracle, но получаю исключение: "cx_Oracle.OperationalError: ORA-03113: конец файла в канале связи".
Мой запрос работает нормально, используя Pycharm (jdbc: oracle: thin driver). Однако, используя cx_Oracle в python 3.6, запрос не будет выполнен, если я не уменьшу количество идентификаторов в предложении IN с 500 до примерно 250. Функция Cursor.fetchall () - это то, что вызывает исключение. У меня нет привилегированного доступа к базе данных для проверки таких вещей, как блокировки или загрузка, но могут ли они быть причиной проблемы? Согласно нашим администраторам баз данных, в сервере Oracle db нет ничего плохого, и, поскольку в противном случае запрос работает нормально, я склонен верить в это. Я также запутался в клиентском sqlnet.ora, который позволял в конечном итоге генерировать исключения, а не зависать навсегда, но я все еще не могу получить данные.
def select(self, query, *args):
cur = self.dbh.cursor()
cur.prepare(query)
try:
cur.execute(None, args)
return cur.fetchall()
# my attempt to handle the issue
except (cx_Oracle.OperationalError, cx_Oracle.DatabaseError) as e:
# cx_Oracle.OperationalError: ORA-03113: end-of-file on communication channel
self.logger.error('Oracle Error: {}'.format(traceback.format_exc()))
raise e
Код звонков выбирается так. Для краткости я опустил полные строковые идентификаторы
ids = ['1', '2', '3', ...]
query = """\
select * from my_table where id in(:0,:1,:2,:3,:4, ...)
"""
self.select(query, *ids)
Сбой запроса также без заполнителей (с идентификаторами, размещенными непосредственно в запросе).
Я ожидаю, что смогу выполнить любой запрос select с помощью предложения IN с 1000 идентификаторами без получения исключения ORA-03113.
Edit:
Я установил на Ubuntu 18.04.2 oracle-instantclient18.5-basic-18.5.0.0.0-3.x86_64.rpm *, у меня cx_Oracle версии 7.1.2, и я подключаюсь к Oracle 12.1.0.2.0.
Запрос находится в базовых таблицах ARS BMC Software. Я начну работать, чтобы попытаться повторить проблему с локальной структурой таблицы, но это беспорядок и займет некоторое время. Если я смогу создать локальную копию таблиц, я не уверен, что смогу воспроизвести проблему, поскольку идентичные запросы с разными идентификаторами работают нормально. Это делает его управляемым данными, однако после того, как я сократил запрос до 250 идентификаторов, я поменял 250 с первой половины на вторую и получил такой же успешный результат, так что, похоже, это не одна плохая строка .
Есть ли более полезная регистрация, которую я могу включить на стороне клиента для получения дополнительной информации?
Edit2: я должен также добавить, что проблема возникает не только с одним запросом. Я видел ту же проблему с запросами на выборку для совершенно разных таблиц.
Edit3: Я только что узнал, что, комментируя некоторые из выбранных мной столбцов, можно заставить запрос работать. такие столбцы:
to_char(to_date('1970-01-01','YYYY-MM-DD') + numtodsinterval(EventStart,'SECOND'),'YYYY-MM-DD HH24:MI:SS')
Это может указывать на то, что истекло время ожидания, которое может быть настроено или не настроено в моем sqlnet.ora:
DISABLE_OOB=on
SQLNET.RECV_TIMEOUT=60
SQLNET.SEND_TIMEOUT=60
TCP.CONNECT_TIMEOUT=300
SQLNET.OUTBOUND_CONNECT_TIMEOUT=300
ENABLE=BROKEN
TRACE_LEVEL_CLIENT=ADMIN
TRACE_FILE_CLIENT=sqlnet
Редактировать 4: я пробовал еще кое-что.
Я установил ту же версию клиента Instant Instant, за исключением Windows 7, и выполнил тот же запрос к тому же экземпляру БД. Запрос успешно выполнен.
Я также сузил, что для этого конкретного запроса он будет принимать 499 идентификаторов, но с 500 не получится. Не имеет значения, какой идентификатор я закомментирую из запроса.
Я также пытался обмануть запрос, думая, что было меньше идентификаторов, используя вместо этого дополнительный выбор:
IN(
select regexp_substr(:0,'[^,]+', 1, level) from dual connect by regexp_substr(:0, '[^,]+', 1, level) is not null
)
Я получил сообщение об ошибке «cx_Oracle.DatabaseError: ORA-01460: запрошено невыполненное или необоснованное преобразование», после чего я понял, что имеет смысл, потому что Oracle допускает длину строки до 4000 байт.