Репликация ИБИС — различия между версиями
(→Настройка и прицип работы) |
Admin (обсуждение | вклад) |
||
| (не показано 29 промежуточных версий 3 участников) | |||
| Строка 1: | Строка 1: | ||
== Общие сведения == | == Общие сведения == | ||
Репликация ИБИС представляет из себя механизм передачи изменяемой в БД информации с одной базы в другую, с использованием DBLink. | Репликация ИБИС представляет из себя механизм передачи изменяемой в БД информации с одной базы в другую, с использованием DBLink. | ||
| − | Вся изменяемая в БД информация накапливается в буфере, а затем из буфера передеётся на удалённые БД. | + | Вся изменяемая в БД информация накапливается в буфере, а затем из буфера передеётся на удалённые БД. В буфер репликации попадают изменяемые данные только тех таблиц БД, которые включены в репликацию. |
| − | В буфер информация попадает при срабатывании тригера | + | В буфер информация попадает при срабатывании тригера таблицы включенной в репликацию. |
Для удобного мониторинга репликации создан модуль: '''aReplicationMon.exe''' | Для удобного мониторинга репликации создан модуль: '''aReplicationMon.exe''' | ||
| Строка 14: | Строка 14: | ||
* 1. Создать схему "replication" в месте со всеми объектами (таблицами и функциями). | * 1. Создать схему "replication" в месте со всеми объектами (таблицами и функциями). | ||
Последняя версия всех объектов находится в MIS3 | Последняя версия всех объектов находится в MIS3 | ||
| + | |||
* 2. Создать пользователя БД "IBIS_REPLICATION" и "LINK2SELF". | * 2. Создать пользователя БД "IBIS_REPLICATION" и "LINK2SELF". | ||
Пользователи создаются таким скриптом: | Пользователи создаются таким скриптом: | ||
| Строка 30: | Строка 31: | ||
Это скрипт может выполнять модуль: aReplicationMon.exe. Для этого необходимо выбрать меню: "Настройки/Первоначальные настройки/Шаг 2". | Это скрипт может выполнять модуль: aReplicationMon.exe. Для этого необходимо выбрать меню: "Настройки/Первоначальные настройки/Шаг 2". | ||
| + | |||
* 3. Настроить список реплицируемых таблиц. Все таблицы подлежащие репликации хрянться в "replication.table_name_list". | * 3. Настроить список реплицируемых таблиц. Все таблицы подлежащие репликации хрянться в "replication.table_name_list". | ||
| Строка 39: | Строка 41: | ||
Список реплицируемых таблиц можно настраивать в модуле: '''aReplicationMon.exe'''. Для этого необходимо выбрать меню: "Настройки/Список реплицируемых таблиц". В появившемся окне отображается список всех таблиц во всех схемах БД. Выбрав одну или несколько записей (в данном окне) можно включить или отключить репликацию выбранных таблиц нажатием кнопки "Включить/Выключить". | Список реплицируемых таблиц можно настраивать в модуле: '''aReplicationMon.exe'''. Для этого необходимо выбрать меню: "Настройки/Список реплицируемых таблиц". В появившемся окне отображается список всех таблиц во всех схемах БД. Выбрав одну или несколько записей (в данном окне) можно включить или отключить репликацию выбранных таблиц нажатием кнопки "Включить/Выключить". | ||
| + | |||
* 4. Настроить список БД с которыми происходит репликация. Список баз данных на которые должны реплицироваться данные находится в таблице: "replication.ibis_base_list". В поле "dbase_name" (этой таблицы) должно быть указано название БД возвращаемое командой "current_database()". | * 4. Настроить список БД с которыми происходит репликация. Список баз данных на которые должны реплицироваться данные находится в таблице: "replication.ibis_base_list". В поле "dbase_name" (этой таблицы) должно быть указано название БД возвращаемое командой "current_database()". | ||
| Строка 55: | Строка 58: | ||
'''При втором''', на всех базах (участвующих в репликации), содержание таблицы "replication.ibis_base_list" должно быть одинаковым! | '''При втором''', на всех базах (участвующих в репликации), содержание таблицы "replication.ibis_base_list" должно быть одинаковым! | ||
При таком режиме репликации "без центральной станции", с каждой станции данные отправляются сразу на все станции из таблицы "replication.ibis_base_list". | При таком режиме репликации "без центральной станции", с каждой станции данные отправляются сразу на все станции из таблицы "replication.ibis_base_list". | ||
| + | |||
| + | ВАЖНО помнить, что в режиме "Без центральной станции" в таблице "replication.ibis_base_list" должна отсутсвовать строка с id=1. | ||
== Обязанности разработчиков == | == Обязанности разработчиков == | ||
| Строка 63: | Строка 68: | ||
end if; | end if; | ||
| + | == Администратору == | ||
| + | |||
| + | Перед запуском репликации, данные во всех таблицах должны быть одинаковые. | ||
| + | Очень ВАЖНО, что бы после запуска репликации на всех БД, в таблицы каждой БД данные вставлялись со смещенными сиквенсами! | ||
| + | Для этого перед запуском репликации требуется делать смещение сиквенсов. | ||
| + | Значение для смещения можно брать из таблицы '''replication.ibis_base_list'''. В этой таблице в поле "'''id'''" находится уникальный идентификатор базы. | ||
| + | |||
| + | В процессе репликации, если между удалёнными таблицами (по какой либо причине) произойдёт раз синхронизация данных, то их можно заравнять выполнив функцию: | ||
| + | |||
| + | replication.dblink_remote_equality($1,$2,$3) | ||
| + | где $1 - имя удалённой БД | ||
| + | $2 - имя таблицы (которую нужно синхронизировать) (например "mm.emp") | ||
| + | $3 - текст SQL запроса выбирающего все данные из таблицы (например "select * from mm.emp") | ||
| + | Эта функция не будет работать если данные раз синхронизированы без смещения сиквенсов. Т.е. если для одного и того же значения поля "'''id'''" в локальной и удалённой таблицах содержаться разные данные. | ||
| + | |||
| + | |||
| + | Примеры запросов: | ||
| + | * Запрос выводит список данных которые есть на удалённой БД в таблице "mm.emp", но отсутствуют в локальной: | ||
| + | SELECT p.* FROM dblink('sg4', 'SELECT * FROM mm.emp') p(id int4, surname varchar, name varchar, patron varchar, birth date, db_user varchar, people_id int8, del int2, post_id int4, dept_id int4, is_visible_shed bool, spec_id int4) | ||
| + | EXCEPT | ||
| + | select e.* from mm.emp e | ||
| + | |||
| + | * Запрос выводит список данных которые есть в локальной БД в таблице "mm.emp", но отсутствуют на удалённой: | ||
| + | select e.* from mm.emp e | ||
| + | EXCEPT | ||
| + | SELECT p.* FROM dblink('sg4', 'SELECT * FROM mm.emp') p(id int4, surname varchar, name varchar, patron varchar, birth date, db_user varchar, people_id int8, del int2, post_id int4, dept_id int4, is_visible_shed bool, spec_id int4) | ||
| + | |||
| + | * Запрос который облегчает написание перечисления типов для команды '''dblink''' в запросах приведённых выше: | ||
| + | SELECT string_agg(a.attname||' '||t.typname,', ') | ||
| + | FROM pg_class c, pg_attribute a, pg_namespace n, pg_type t | ||
| + | WHERE n.nspname||'.'||c.relname = 'mm.emp' | ||
| + | AND a.attnum > 0 | ||
| + | AND a.attrelid = c.oid | ||
| + | AND c.relkind = 'r' | ||
| + | AND a.attname !~ '.pg.' | ||
| + | AND c.relnamespace=n.oid | ||
| + | AND a.atttypid = t.oid | ||
| + | |||
| + | * Далее приведён запрос составленный из первых двух запросов. В нём выбираются данные из удалённой БД '''sg4''' и локальной '''sg42'''. В результате его выполнения отображаются данные которые отсутствуют в одной из БД (локальной и удалённой). Так же в нём можно увидеть пересекающиеся "'''id'''". Т.е. когда в строках с одинаковым "'''id'''" содержатся разные данные. | ||
| + | SELECT 'sg4', p.* FROM dblink('sg4', 'SELECT * FROM mm.emp') p(id int4, surname varchar, name varchar, patron varchar, birth date, db_user varchar, people_id int8, del int2, post_id int4, dept_id int4, is_visible_shed bool, spec_id int4) | ||
| + | EXCEPT | ||
| + | select 'sg4', e.* from mm.emp e | ||
| + | union all -- | ||
| + | select 'sg42', e.* from mm.emp e | ||
| + | EXCEPT | ||
| + | SELECT 'sg42', p.* FROM dblink('sg4', 'SELECT * FROM mm.emp') p(id int4, surname varchar, name varchar, patron varchar, birth date, db_user varchar, people_id int8, del int2, post_id int4, dept_id int4, is_visible_shed bool, spec_id int4) | ||
| + | order by surname, 1,2 | ||
| + | |||
| + | |||
| + | Задание для pgAgent [[Репликация]] | ||
[[Category:Руководство программиста MIS3]] | [[Category:Руководство программиста MIS3]] | ||
Текущая версия на 11:02, 17 мая 2016
Содержание
Общие сведения
Репликация ИБИС представляет из себя механизм передачи изменяемой в БД информации с одной базы в другую, с использованием DBLink. Вся изменяемая в БД информация накапливается в буфере, а затем из буфера передеётся на удалённые БД. В буфер репликации попадают изменяемые данные только тех таблиц БД, которые включены в репликацию. В буфер информация попадает при срабатывании тригера таблицы включенной в репликацию.
Для удобного мониторинга репликации создан модуль: aReplicationMon.exe
На первой закладке он отображает состояние подключений к удалённым БД и список ошибок, возникших при репликации. Список ошибок отображается отдельно для каждой БД верхнего списка. На второй закладке он отображает полный список ошибок (ошибок всех БД). Из этого списка можно удалять ошибки вместе с данными (находящимися в буфере для отправки) на которых данная ошибка произошла. Таким образом можно очистить буфер передачи подготовленных данных. Так же в данном модуле начата разработка пошагового механизма первоначальной настройки репликации. Он доступен в меню "Настройки".
Настройка и прицип работы
Для использования механизма репликации необходимо:
- 1. Создать схему "replication" в месте со всеми объектами (таблицами и функциями).
Последняя версия всех объектов находится в MIS3
- 2. Создать пользователя БД "IBIS_REPLICATION" и "LINK2SELF".
Пользователи создаются таким скриптом:
DROP USER IF EXISTS "LINK2SELF"; CREATE USER "LINK2SELF" INHERIT LOGIN; ALTER USER "LINK2SELF" PASSWORD 'IbisPticaZloy'; GRANT "MIS_USER" to "LINK2SELF"; ALTER ROLE "MIS_USER" CREATEROLE;
DROP USER IF EXISTS "IBIS_REPLICATION"; CREATE USER "IBIS_REPLICATION" INHERIT LOGIN; ALTER USER "IBIS_REPLICATION" PASSWORD 'IbisPticaZloy'; GRANT "MIS_USER" to "IBIS_REPLICATION"; ALTER ROLE "MIS_USER" CREATEROLE;
Это скрипт может выполнять модуль: aReplicationMon.exe. Для этого необходимо выбрать меню: "Настройки/Первоначальные настройки/Шаг 2".
- 3. Настроить список реплицируемых таблиц. Все таблицы подлежащие репликации хрянться в "replication.table_name_list".
В данной таблице, поле "tbl_name" должно быть указано имя таблицы вместе с именем схемы, например: "mm.emp". В поле "enable_b" должно быть установлено значение True. Если занчение False, то указанная таблица исключается из репликации.
ВАЖНО знать, что при присвоении полю "enable_b" значения True, для указанной таблицы автоматически создаются два тригера: "replication_triger_row" и "replication_triger_stmnt". Таким образом на таблице (включенной в репликацию) тригер "replication_triger_row" добавляет все изменяемые данные таблицы в буфер репликации, в таблицу "replication.ibis_to_send", а тригер "replication_triger_stmnt" (по окнчании изменения данных) запускает процедуру "replication.ibis_start_send()". Данная процедура, в свою очередь, запускает функцию "replication.send_data()", которая читает данные из буфера и отправляет их на удалённые БД.
В функции "replication.send_data()" встроен механизм исключающий слишком частый её запуск. Т.е. если эта функция будет запущена менее чем через 10 сек после предыдущего запуска, то она сразу завершит свою работу. Это исключает запуск этой функции при каждом изменении данных в реплицируемой таблице. Данный механизм был реализован с целью исключения реализации мехнизма запуска передачи данных из шедулера.
Список реплицируемых таблиц можно настраивать в модуле: aReplicationMon.exe. Для этого необходимо выбрать меню: "Настройки/Список реплицируемых таблиц". В появившемся окне отображается список всех таблиц во всех схемах БД. Выбрав одну или несколько записей (в данном окне) можно включить или отключить репликацию выбранных таблиц нажатием кнопки "Включить/Выключить".
- 4. Настроить список БД с которыми происходит репликация. Список баз данных на которые должны реплицироваться данные находится в таблице: "replication.ibis_base_list". В поле "dbase_name" (этой таблицы) должно быть указано название БД возвращаемое командой "current_database()".
ВАЖНО знать, что все базы данных участвующие в репликации, должны иметь уникальные имена "current_database()"! В поле "owner_ip" таблицы "replication.ibis_base_list", должен быть указан внешний IP адрес (который виден в сети с других компьютеров, участвующих в репликации). По возможности вместо IP лучше указывать сетевое имя компьютера, т.к. в данном случае смена настроек сетевого адаптера не нарушит связь репликации. В поле "owner_port", должен быть указан внешний порт, по которому будут подключаться к БД компьютеры в сети. В поле "is_replication" должно быть указано значение True. Если будет указано значение False, то на указанную БД не будет происходить отправка данных.
Можно настроить дав вида репликации. Первый, это когда среди баз (участвующих в репликации) выделяется одна - "Центральная". Второй, это когда все базы равны и "Центральная" отсутствует.
При первом, на "Центральной" БД в таблице "replication.ibis_base_list" указываются все БД участвующие в репликации, а на "Не центральных" БД в таблице "replication.ibis_base_list" указывается только одна ("Центральная") база. Так же ВАЖНО - в таблице "replication.ibis_base_list" для "Центральной" БД указано значение поля "id" должно быть = 1! При отправке данных на неё (с "Не центральных" БД), на ней данные будут не только вставляться в таблицы БД но и дублироваться в буферную таблицу для отправки на другие БД.
При втором, на всех базах (участвующих в репликации), содержание таблицы "replication.ibis_base_list" должно быть одинаковым! При таком режиме репликации "без центральной станции", с каждой станции данные отправляются сразу на все станции из таблицы "replication.ibis_base_list".
ВАЖНО помнить, что в режиме "Без центральной станции" в таблице "replication.ibis_base_list" должна отсутсвовать строка с id=1.
Обязанности разработчиков
Все разработчики при создании тригеров на таблицах, в самое начало тригера, после "BEGIN" должны вставлять следующий код:
if session_user = 'IBIS_REPLICATION' then -- Если измения произошли от пользователя репликации IBIS_REPLICATION
RETURN null; -- то выходим из тригера, т.к. это результат действий репликации
end if;
Администратору
Перед запуском репликации, данные во всех таблицах должны быть одинаковые. Очень ВАЖНО, что бы после запуска репликации на всех БД, в таблицы каждой БД данные вставлялись со смещенными сиквенсами! Для этого перед запуском репликации требуется делать смещение сиквенсов. Значение для смещения можно брать из таблицы replication.ibis_base_list. В этой таблице в поле "id" находится уникальный идентификатор базы.
В процессе репликации, если между удалёнными таблицами (по какой либо причине) произойдёт раз синхронизация данных, то их можно заравнять выполнив функцию:
replication.dblink_remote_equality($1,$2,$3) где $1 - имя удалённой БД $2 - имя таблицы (которую нужно синхронизировать) (например "mm.emp") $3 - текст SQL запроса выбирающего все данные из таблицы (например "select * from mm.emp")
Эта функция не будет работать если данные раз синхронизированы без смещения сиквенсов. Т.е. если для одного и того же значения поля "id" в локальной и удалённой таблицах содержаться разные данные.
Примеры запросов:
- Запрос выводит список данных которые есть на удалённой БД в таблице "mm.emp", но отсутствуют в локальной:
SELECT p.* FROM dblink('sg4', 'SELECT * FROM mm.emp') p(id int4, surname varchar, name varchar, patron varchar, birth date, db_user varchar, people_id int8, del int2, post_id int4, dept_id int4, is_visible_shed bool, spec_id int4)
EXCEPT
select e.* from mm.emp e
- Запрос выводит список данных которые есть в локальной БД в таблице "mm.emp", но отсутствуют на удалённой:
select e.* from mm.emp e
EXCEPT
SELECT p.* FROM dblink('sg4', 'SELECT * FROM mm.emp') p(id int4, surname varchar, name varchar, patron varchar, birth date, db_user varchar, people_id int8, del int2, post_id int4, dept_id int4, is_visible_shed bool, spec_id int4)
- Запрос который облегчает написание перечисления типов для команды dblink в запросах приведённых выше:
SELECT string_agg(a.attname||' '||t.typname,', ')
FROM pg_class c, pg_attribute a, pg_namespace n, pg_type t
WHERE n.nspname||'.'||c.relname = 'mm.emp'
AND a.attnum > 0
AND a.attrelid = c.oid
AND c.relkind = 'r'
AND a.attname !~ '.pg.'
AND c.relnamespace=n.oid
AND a.atttypid = t.oid
- Далее приведён запрос составленный из первых двух запросов. В нём выбираются данные из удалённой БД sg4 и локальной sg42. В результате его выполнения отображаются данные которые отсутствуют в одной из БД (локальной и удалённой). Так же в нём можно увидеть пересекающиеся "id". Т.е. когда в строках с одинаковым "id" содержатся разные данные.
SELECT 'sg4', p.* FROM dblink('sg4', 'SELECT * FROM mm.emp') p(id int4, surname varchar, name varchar, patron varchar, birth date, db_user varchar, people_id int8, del int2, post_id int4, dept_id int4, is_visible_shed bool, spec_id int4)
EXCEPT
select 'sg4', e.* from mm.emp e
union all --
select 'sg42', e.* from mm.emp e
EXCEPT
SELECT 'sg42', p.* FROM dblink('sg4', 'SELECT * FROM mm.emp') p(id int4, surname varchar, name varchar, patron varchar, birth date, db_user varchar, people_id int8, del int2, post_id int4, dept_id int4, is_visible_shed bool, spec_id int4)
order by surname, 1,2
Задание для pgAgent Репликация