понедельник, 8 августа 2011 г.

Скрипт создания и удаления очередей в оракле.

Дано:
Схема AQ - содержит очереди.
Схема A - оперирует очередями и содержит процедуру-подписчик, которая будет вызываться во время извлечения задания из очереди


begin
-- создаем таблицу для очереди, multiple_consumers - параметр для мультиподписчиков, queue_payload_type - тип данных, который будет хранится в очереди
dbms_aqadm.create_queue_table(queue_table => 'AQ.DIRECTADMIN_Q_TBL',
queue_payload_type => 'sys.xmltype',
multiple_consumers => true);

-- создаем саму очередь, привязанную к таблице
dbms_aqadm.create_queue(queue_name => 'AQ.DIRECTADMIN_Q',
queue_table => 'AQ.DIRECTADMIN_Q_TBL');

-- выдаем привилегии для нужной схемы
dbms_aqadm.grant_queue_privilege(privilege => 'ALL',
queue_name => 'AQ.DIRECTADMIN_Q',
grantee => 'A',
grant_option => false);
-- выдаем привилегии на таблицу очереди, если нужно
--exec grant select , update, delete on AQ.DIRECTADMIN_Q_TBL to A;

-- запускаем очередь
dbms_aqadm.start_queue(queue_name => 'AQ.DIRECTADMIN_Q');

-- добавляем подписчика к очереди
dbms_aqadm.add_subscriber(queue_name => 'AQ.DIRECTADMIN_Q',
subscriber => sys.aq$_agent('DIRECTADMIN_Q_SUBSCRIBER',
NULL,
NULL));

-- регистрируем подписчика и делаем привязку к процедуре, которая вызовется при извлечении задания
dbms_aq.register(sys.aq$_reg_info_list(sys.aq$_reg_info('AQ.DIRECTADMIN_Q:DIRECTADMIN_Q_SUBSCRIBER',
dbms_aq.namespace_aq,
'PLSQL://A.PKG_QUEUE_CALLBACK.DIRECTADMIN',
HEXTORAW('FF'))),
1);

-- удаление очереди
/* dbms_aqadm.stop_queue(queue_name => 'AQ.DIRECTADMIN_Q');
dbms_aqadm.drop_queue(queue_name => 'AQ.DIRECTADMIN_Q');
dbms_aqadm.drop_queue_table(queue_table => 'AQ.DIRECTADMIN_Q_TBL');*/

end;

-- Ручной запуск обработчика очередей begin dbms_aqadm_sys.register_driver(); end;

среда, 27 июля 2011 г.

Восстановление оракла из бэкапа (лайт версия)

Есть бэкап базы оракла (контрол-файлы, дата файлы и т.д.). Есть сервер с установленным ораклом, SID должен совпадать с SID'ом базы, с которой сделан бэкап.

0. Останавливаем базу данных (все действия через rman connect target /)
shutdown immediate;

Удаляем все файлы данных и логи новой базы, что бы не мешались.

startup nomount;

1. Восстанавливаем spfile.
restore spfile to '/home/oracle/spfile.last' from '/u01/db1_rman/CF_DB1_c-1328626743-20110727-00.bus';

где CF_DB1_c-1328626743-20110726-00.bus бэкап контрол-файлов (есди настроена retention policy, то это самый последний-свежий файл).

Теперь копируем восстановленный файл параметров заместо старого.
cp /home/oracle/spfile.last /u01/app/oracle/product/11.2.0/dbhome_1/dbs/spfiledb1.ora

2. Поднимаем базу в nomount режиме
shutdown immediate;
startup nomount;

(Может ругнутся на недоступность некоторых директорий - их нужно создать и выдать соответствующие права)

3. Восстанавливаем контрол-файлы.
restore controlfile from '/nfsbackup/db1_rman/CF_DB1_c-1328626743-20110726-00.bus'

4. Монтируем базу данных.
alter database mount;

5. Указываем файлы бэкапа данных базы.
Что бы бэкапы "подошли" к новой базе dbid в заголовке базы должен совпадать с текущим. Обычно после восстановления spfile, контрол-файлов и перезагрузки базы в mount, dbid должен соответствовать dbid базы с которой снят бэкап. Если это не так делаем
set dbid 1328626743
1328626743 - dbid вашей базы с которой снят бэкап (если не в курсе где его брать, то он указан в ошибках)

Далее добавляем в каталог файлы бэкапов
catalog backuppiece '/nfsbackup/db1_rman/DB1_1275980815_20110719_939_1.bus';
catalog backuppiece '/nfsbackup/db1_rman/DB1_1275980815_20110719_939_1.bus';
catalog backuppiece '/nfsbackup/db1_rman/DB1_1275980815_20110719_940_1.bus';
...


Если исользуется retention policy - то нужно указать все файлы бэкапов данных.
Либо
catalog start with '/nfsbackup/db1_rman/';
Будут каталогизированы все файлы в этой директории.

6. Восстанавливаем базу.
restore database;

7. Накатываем изменения (архивлоги).
recover database;

8. Открываем базу.
Что бы джобы не запустились сразу, можно использовать в sqlplus следующий параметр:
alter system set JOB_QUEUE_PROCESSES = 0; (Потом обязательно не забыть его поменять!)
alter database open resetlogs;

понедельник, 13 июня 2011 г.

Что не так с вашим Singleton'ом?

Есть классическая реализация паттерна Singleton в Java для многопоточного использования. Так называемый double-checked locking.

  1.  
  2. public class Singleton {
  3.     private static Singleton instance;
  4.  
  5.     private Singleton {
  6.     }
  7.  
  8.     public static Singleton getInstance() {
  9.        if(instance == null) {
  10.             synchronized(this) {
  11.                if(instance == null) {
  12.                   instance = new Singleton();
  13.                }
  14.             }
  15.        }
  16.        return instance;
  17.     }
  18. }
  19.  

По логике все прекрасно, и создание объекта on-demand (ленивая инициализация), и не блокирующие чтение. Но, к сожалению, в некоторых случаях данный Singleton будет вести себя плохо. В чем же причина? Все дело в нюансах работы JVM с памятью, в многопоточной среде. Прежде чем описать проблему и приступить к решению, нужно вспомнить основные идиомы синхронизации при работе с памятью.
 — Атомарность. Целостность доступа (чтения и записи) к переменной в памяти. Гарантия что при запросе переменной будет возвращено ее значение либо до изменения одним из потоков, либо после. Но никак не промежуточное состояние (набор битов старого значения переписанное частично другим потоком).
 — Видимость. Видимость переменных измененных одним потоком в контексте другого.
 — Упорядоченность. Последовательно выполнение команд скомпилированного кода.

Если блок кода или метод синхронизирован, то все изменения, сделанные в контексте одного потока, атомарны, видимы для остальных потоков (использующих туже блокировку) и выполняются последовательно в соответствие с порядком кода в программе. Если синхронизации нет — все вышесказанное не гарантировано. Где же теряется синхронизация в нашем примере? Самое очевидное это отсутствие упорядоченности в строке instance = new Singleton ();. Когда компилятор видит конструктор, который не выбрасывает исключений и не выполняется синхронизированно, он может свободно поменять порядок инициализации объекта и его запись в перменную instance. Даже если порядок записи не меняется компилятором, он может быть изменен процессором в мультипроцессорной среде или самой системой памяти.
Самое важное в данной ситуации не придумывать велосипед, т.к. решая одну проблему синхронизации можно напороться на другую, которая проявит себя в специфичной ситуации совершенно не к месту. Многие гуру бились над этой проблемой и выработали приемлемые решения. Приводить обзор всех вариантов я не буду, укажу лишь только то, что использую сам.

1. Класс-холдер.

  1.  
  2. public class Singleton {
  3.  
  4.     private Singleton {
  5.     }
  6.    
  7.     private static class SingletonHolder {
  8.        private final static Singleton instance = new Singleton();
  9.     }
  10.  
  11.     public static Singleton getInstance() {
  12.        return SingletonHolder.instance;
  13.     }
  14. }
  15.  

Красивый способ, без явной синхронизации, инициализация on-demand. Но конструктор не должен выбрасывать эксепшенов, если есть уверенность что исключений не будет — используем этот вариант.

2. Доработанный double-checked locking пример.

  1.  
  2. public class Singleton {
  3.     private volatile static Singleton instance;
  4.  
  5.     private Singleton {
  6.     }
  7.  
  8.     public static Singleton getInstance() {
  9.        if(instance == null) {
  10.             synchronized(this) {
  11.                if(instance == null) {
  12.                   instance = new Singleton();
  13.                }
  14.             }
  15.        }
  16.        return instance;
  17.     }
  18. }
  19.  

Модификатор volatile гарантирует синхронизированное обращение к перменной instance. Но работает только на jdk 5 и выше.

Статья изложена, осознана, переведена с использованием источников:

Реализация Singleton в JAVA

Synchronization and the Java Memory Model

The «Double-Checked Locking is Broken» Declaration
______________________
Текст подготовлен в Редакторе Блогов от © SoftCoder.ru

суббота, 2 апреля 2011 г.

Syntax highlighter



1. http://highlight.hohli.com/

- oracle
  1. SELECT * FROM dual;

- java
  1. public class HelloWorld {
  2. public static void main(String[] arg) {
  3. System.out.println("Hello world!");
  4. System.out.println("Hello world!");
  5. System.out.println("Hello world!");
  6. System.out.println("Hello world!");
  7. System.out.println("Hello world!");
  8. System.out.println("Hello world!");
  9. }
  10. }

2. http://s-c.me/
Copy Source | Copy HTML
  1. select * from dual;

3. http://www.softcoder.ru/blogeditor/

 — oracle

  1. DECLARE
  2. l_number NUMBER;
  3. BEGIN
  4.    SELECT 1 INTO l_number FROM dual;
  5. EXCEPTION WHEN OTHERS THEN RAISE;  
  6. END;

 — java

  1. public class HelloWorld {
  2.    public static void main(String[] arg) {
  3.       System.out.println("Hello world!");
  4.          
  5.       System.out.println("Hello world!");
  6.       System.out.println("Hello world!");
  7.       System.out.println("Hello world!");
  8.       System.out.println("Hello world!");
  9.       System.out.println("Hello world!");
  10.    }  
  11. }

______________________
Текст подготовлен в Редакторе Блогов от © SoftCoder.ru



4. http://dumpz.org

- oracle
select * from dual;

- java
public class HelloWorld {
public static void main(String[] arg) {
System.out.println("Hello world!");
System.out.println("Hello world!");
System.out.println("Hello world!");
System.out.println("Hello world!");
System.out.println("Hello world!");
System.out.println("Hello world!");
}
}
Colored with dumpz.org
З.Ы. Как видно, самый адекватный хайлайтер от софткодера.