Как отменить длительную операцию базы данных?
В настоящее время работает с Oracle, но также потребуется решение для MS SQL.
У меня есть графический интерфейс, который позволяет пользователям генерировать SQL, который будет выполнен в базе данных. Это может занять очень много времени, в зависимости от поиска, который они создают. Я хочу, чтобы GUI / App реагировал во время этого поиска, и я хочу, чтобы пользователь мог отменить поиск.
Я использую тему рабочего рабочего.
- Что такое двойная таблица в Oracle?
- Невозможно использовать запрос LIKE в JDBC PreparedStatement?
- ojdbc14.jar против ojdbc6.jar
- if (выберите count (столбец) из таблицы)> 0, тогда
- Как получить хорошо отформатированные результаты из процедуры Oracle, которая возвращает ссылку на указатель?
Моя проблема в том, что, когда пользователь отменяет поиск, я не могу прерывать вызов в базу данных. Он ждет, пока он не будет завершен, и затем он сможет опросить свойство «Отмена». Это не только ресурсы отходов в базе данных, но и создает проблемы для моего кода.
Если пользователь нажимает «Поиск» по очень длинному запросу, затем нажимает «Отмена», а затем снова «Поиск» – первый поиск по-прежнему прерывается в базе данных. Фоновый рабочий все еще занят, когда они снова находят поиск. Единственное решение, с которым я столкнулся, состоит в том, чтобы создать нового фонового работника.
Кажется, это действительно уродливый способ сделать что-то. База данных продолжает работать. Я создаю новые экземпляры фоновых работников …. когда я действительно хочу остановить вызов базы данных и повторно использовать одного и того же работника.
Как я могу это сделать?
- Как обратиться к ошибке «Получите минус один из чтения» при подключении к экземпляру Oracle Amazon RDS
- Oracle Database Link - эквивалент MySQL?
- В Oracle можно ли вставить или ОБНОВИТЬ запись через представление?
- Подключение к Oracle Database через C #?
- Проблема прерывания Oracle JDBC
- Как я могу описать таблицу в Oracle без использования команды DESCRIBE?
- Можем ли мы обновить значения первичных ключей таблицы?
- Получать подсчеты всех таблиц в схеме
Я не думаю, что это возможно. Вот ссылка на дискуссию на веб-сайте Oracle по этой теме: http://forums.oracle.com/forums/thread.jspa?threadID=400492&start=15&tstart=0
Если вы используете поставщик данных ADO.NET и SQL, посмотрите на метод SqlCommand.Cancel. Это делает то, что вы ищете. Тем не менее, он пытается отменить, и отмена может занять некоторое время. В основном, SQL Server должен решить, когда следует предоставить запрос на отмену. Когда запрос отменяется, вы должны получить исключение SqlException, которое указывает, что операция была отменена пользователем. По-видимому, вы не хотите рассматривать это исключение как исключение и обрабатывать его специально, например, если SqlException вызван тем, что пользователь отменил операцию, просто проглотите ее.
Я также заметил, что command.Cancel () не отменяет команду. То, что сработало для меня, – это закрытие соединения (транзакция возврата, если вы используете ее), когда пользователь прерывается. Это приведет к возникновению исключения в фоновом streamе во время выполнения команды, поэтому вам придется поймать его и проверить свойство CancellationPending, а не отменять исключение в этом случае …
// When aborting worker.CancelAsync(); command.Connection.Close(); // In your DoWork event handler ... catch (Exception) { if (worker.CancellationPending) { e.Cancel = true; return; } else { throw; } } // And in your RunWorkerCompleted event handler if (e.Error == null && !e.Cancelled) { ... }
Я уверен, что это возможно – мы используем TOAD для Oracle, и он позволяет отменить длительные запросы, как описано здесь . Я не уверен, как они это делают.
Вы могли бы заставить фонового рабочего отключить фактический вызов базы данных в другом streamе, а затем периодически проверять, завершен ли вызов базы данных или отменили отмену, после чего вы можете убить stream базы данных. Это фактически не помогло бы загрузке базы данных (как ваш запрос был отправлен и по-прежнему обрабатывается), но он освобождает ваши локальные ресурсы, связанные с ним.
Я думаю, что лучшее решение, похоже, убивает сеансы через таблицу мониторинга.
С Oracle вы можете сделать это, как говорит Burnsys
В Firebird 2.5 он будет выглядеть одинаково
Я надеюсь, что что-то подобное существует в Ms SQL
Если вы используете SQLCommand, вы можете попробовать вызвать метод « Отмена» .
Как насчет открытия нового подключения к базе данных, войдите в систему как sysdba и отправьте команду «ALTER SYSTEM KILL SESSION» sid, серийный номер «IMMEDIATE», указав SID процесса, который вы хотите завершить.
Чтобы получить sessionID: выберите sid из v $ mystat, где rownum = 1
Чтобы получить Serial #: выберите sid, serial # из v $ session, где sid =: SID
http://www.oracle-base.com/articles/misc/KillingOracleSessions.php
EDIT: идея WWW не для входа в систему как sysdba здесь: http://forums.oracle.com/forums/thread.jspa?threadID=620578
Я пробовал как Отменить, так и закрыть с ADO 2.8 и SQLOLEDB или SQL Server родным клиентом. С помощью Отмена набор записей перестает извлекать данные, но на заднем плане чтение с сервера продолжается и потребляет память из приложения. В 32-битном приложении может случиться, что через несколько минут вы получите сообщение «из памяти». Когда я закрываю набор записей (или соединение, с или без отмены до), ADO 2.8 ждет, пока все записи не будут извлечены.
Я не знаю, улучшает ли ADO.NET, но я думаю, что неплохо следить за памятью и доступом к сети после Cancel / Close, чтобы быть уверенным, что ADO действительно перестает читать данные.