|
Программирование >> Oracle
1632 Приложение А Идея здесь в том, чтобы в триггере брать первичн1й ключ таблицы и помещать его значение в строку символов. После этого можно использовать функцию DBMS UTILITY.GET HASH VALUE для получения почти уникального хеш-значения для строки. Если использовать хеш-таблицу размером не более 1073741823 значений, можно будет заблокировать это значение в исключительном режиме с помощью пакета DBMS LOCK. Можно также использовать подпрограмму ALLOCATE UNIQUE пакета DBMS LOCK, но на это потребуются дополнительные ресурсы. Подпрограмма ALLOCATE UNIQUE создает уникальный идентификатор блокировки в диапазоне от 1073741824 до 1999999999. Для этого она использует другую таблицу в базе данных и рекурсивную (автономную) транзакцию. Благодаря хешированию используется меньше ресурсов и, кроме того, можно избежать вызова рекурсивнгх SQL-операторов. После хеширования мы берем полученное значение и с помощью пакета DBMS LOCK запрашиваем блокировку с соответствующим идентификатором в исключительном режиме с нулевым временем ожидания (если значение кем-то уже заблокировано, происходит немедленный возврат). Если получить блокировку за это время не удалось, возбуждается исключительная ситуация ORA-54 RESOURCE BUSY. B противном случае можно выполнить оператор INSERT, и он не будет заблокирован. Конечно, если в качестве первичного ключа таблицы используется целое число и есть уверенность, что значения ключа не превысят 1 миллиарда, можно его не хешировать, а использовать непосредственно в качестве идентификатора блокировки. Нужно поиграть с размером хеш-таблицы (в моем примере - 1024), чтобы избежать сообщений RESOURCE BUSY, связанных с получением одного и того же хеш-значения по разным строкам. Размер хеш-таблицы зависит от приложения (точнее, от используемых данных); на него также влияет количество одновременно выполняемых вставок. Кроме того, владельцу триггера понадобится непосредственно (не через роль) предоставленная привилегия EXECUTE на пакет DBMS LOCK. Наконец, при вставке большого количества строк таким способом, без фиксации может не хватить ресурсов ENQUEUE RESOURCES. В случае возникновения такой проблемы (при этом генерируется соответствующее сообщение) необходимо увеличить значение параметра инициализации ENQUEUE RESOURCES. Можно также добавить в триггер флаг, позволяющий включать и отключать эту проверку. Например, если бы я планировал вставлять сотни/тысячи записей, то не хотел бы выполнять подобную проверку при каждой вставке. Пользовательские блокировки, а также количество первичных ключей с соответствующим хеш-значением, можно получить из представления V$LOCK. Например, если такой триггер был установлен для рассмотренной в предыдущих примерах таблицы DEMO, мы получим: tkyte@TKYTE816> insert into demo values (1); 1 row created. tkyte@TKYTE816> select sid, type, idl 2 from v$lock 3 where sid = (select sid from v$mystat where rownum = 1) SID TY ID1 8 ТХ 589913 Пакет DBMS LOCK 1633 8 ТМ 30536 б UL 827 tkyte@TKYTE816> begin 2 dbms output.put line 3 (dbms utility.get hash value(to char(l), 0, 1024)); 4 end; 5 / 827 PL/SQL procedure successfully completed. Обратите внимание на пользовательскую блокировку UL со значением ID1 827. Оказывается, что 827 - хеш-значение для результата функции TO CHAR(1), примененной к первичному ключу. Чтобы завершить этот пример, нужно разобраться, что произойдет, если приложение допускает изменение первичного ключа. В идеале первичный ключ лучше не изменять, но некоторые приложения это делают. Надо учитывать последствия того, если один сеанс изменит значение первичного ключа: tkyte@TKYTE816> update demo set x = 2 where x = 1; 1 row updated. а другой сеанс попытается вставить строку с измененным значением первичного ключа: tkyte@TKYTE816> INSERT INTO DEMO VALUES (2); Второй сеанс опять окажется заблокированным. Проблема в том, что не каждый процесс, который может изменить первичный ключ, учитывает измененную схему блокирования. Для решения этой проблемы, связанной с изменением первичного ключа, необходимо изменить событие, вызывающее срабатывание триггера: before insert OR UPDATE OF X on demo Если созданный триггер срабатывает до вставки данных в столбец X или каких-либо изменений его значения, будет происходить именно то, что требуется (и изменение тоже станет неблокирующим). Резюме Пакет DBMS LOCK открывает приложениям доступ к внутреннему механизму блокирования сервера Oracle. Как б1ло продемонстрировано, эту возможность можно ис-пользоватьдля реализации специфического метода блокирования, расширяющего стандартные возможности. Мы рассмотрели способы использования этого механизма для обеспечения очередности доступа к общему ресурсу (например, к файлу ОС) и для координации конфликтующих процессов. Мы углубленно изучили использование средств пакета DBMS LOCK для предотвращения блокирующих вставок. Этот пример показал особенности использования пакета DBMS LOCK, а также отображение информации о соответствующих блокировках в представлении V$LOCK. В завершение я обратил ваше внимание на важность обеспечения координации действий сеансов, связанных со специфическим методом блокирования, описав, как изменение значения первичного ключа может нарушить работу созданного неблокирующего алгоритма вставок. Пакет DBMS LOGMNR Пакеты LogMiner, DBMS LOGMNR и DBMS LOGMNR D, позволяют анализировать файлы журнала повторного выполнения сервера Oracle. Этот анализ может потребоваться в таких случаях: Необходимо определить, когда и кем таблица б1ла удалена. Необходимо проверить, какие действия выполнялись с таблицей или набором таблиц, чтобы разобраться, кто и что изменял. Такую проверку можно в1полнить постфактум . Обычно достаточно выполнить команду AUDIT (но ее надо выполнять заранее), и вы узнаете, что кто-то изменил таблицу, а вот что именно было изменено узнать таким образом невозможно. Пакеты LogMiner позволяют определить постфактум лицо, внесшее изменения, и какие именно данные были изменены. Необходимо отменить транзакцию. Для этого надо узнать, что б1ло сделано в этой транзакции, и создать PL/SQL-код для отмены этих действий. Необходимо получить эмпирические значения количества строк, изменяемых типичной транзакцией. Необходимо выполнить ретроспективный анализ использования базы данн1х за определенный период времени. Необходимо определить, почему сервер вдруг стал генерировать в журнал по 10 Мбайт данных в минуту. Можно ли найти очевидные причины при беглом просмотре журналов?
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |