3. Репликация СУБД#
Репликация - это перенос изменений структуры и данных из одной базы в другую. Репликация реализована как процесс передачи журналов изменений из базы-отправитель в базу-получатель, и последующее применение этого журнала в базе-получатель. Журналы изменений переносятся в формате журнала Xlog.
3.1. Ограничения репликации.#
Репликационная пара - это пара соответствующих объектов репликации,
каждый из которых находится на разных репликационных узлах, и имеющих одинаковое имя.
Объект репликации - это новый тип схемы, который является логическим объединением репликационных пар,
и имеющий свои репликационные настройки. Возможно управление командами текущим состоянием этого объекта.
Ограничения репликации:
Реплицируются только данные в таблицах. Другие объекты схем не реплицируются.
DDL команды по умолчанию не разрешены по таблицам репликации.
Две таблицы, которые составляют репликационную пару, должны быть идентичными по структуре.
Все таблицы, участвующие в репликакции, должны иметь Первичный ключ.
Не разрешается проводить UPDATE по столбцам, входящим в Первичный ключ.
Есть механизмы автоматического разрешения конфликтов репликации.
3.2. Типы репликаций.#
По методу применения журналов в базе-получатель репликация может быть:
Lazy (асинхронная репл.) - для завершения транзакции база-отправитель не ждет завершения применения изменения в базе-получатель.
Это режим по умолчанию.
Eager (синхронная репл.) - для завершения транзакции база-отправитель ожидает завершения применения изменения в базе-получатель.
Репликация будет влиять на производительность базы-отправитель в большей степени, чем в первом случае.
По топологической структуре репликация может быть:
Active - StandBy - когда база-отправитель единственная.
Active - Active - когда баз-отправителей несколько.
3.3. Настройка репликации (пример).#
3.3.1. Создаем контейнеры для репликации#
Создаем и запускаем два контейнера для репликации с именами dbvm-redos-pr (primary) и dbvm-redos-by (standby):
docker run --name dbvm-redos-pr -it --rm -e MODE=shell -e MASTER_REP_PORT=35001 -u altibase registry.dbvm.com/dbvm-redos-7.3
docker run --name dbvm-redos-by -it --rm -e MODE=shell -e MASTER_REP_PORT=35001 -u altibase registry.dbvm.com/dbvm-redos-7.3
3.3.2. ИП-адреса запущенных контейнеров#
Определяем ИП-адреса этих контейнеров:
docker inspect dbvm-redos-pr | grep IPAddress
"IPAddress": "10.88.0.68",
docker inspect dbvm-redos-by | grep IPAddress
"IPAddress": "10.88.0.69",
Для данного запуска ИП-адреса контейнеров такие:
dbvm-redos-pr 10.88.0.68
dbvm-redos-by 10.88.0.69
3.3.3. Создаем схемы в контейнерах#
Подключаемся к базе в каждом контейнере (dbvm-redos-pr и dbvm-redos-by), выполнив команду:
В запущенном клиенте базы в каждом контейнере (dbvm-redos-pr и dbvm-redos-by) выполняем следующие команды:
-- dbvm-redos-pr (10.88.0.68)
-- dbvm-redos-by (10.88.0.69)
-- Проверяем порт репликации
CONNECT sys/manager as sysdba;
iSQL(sysdba)> set vertical on;
iSQL(sysdba)> SELECT NAME, VALUE1 FROM V$PROPERTY WHERE NAME = 'REPLICATION_PORT_NO';
NAME : REPLICATION_PORT_NO
VALUE1 : 35001
1 row selected.
-- dbvm-redos-pr (10.88.0.68)
-- dbvm-redos-by (10.88.0.69)
-- Создаем схему hh/hh
CONNECT sys/manager as sysdba;
CREATE USER hh IDENTIFIED BY hh DEFAULT TABLESPACE SYS_TBS_DISK_DATA;
-- dbvm-redos-pr (10.88.0.68)
-- dbvm-redos-by (10.88.0.69)
-- Создаем таблицу для репликации
CONNECT hh/hh;
DROP TABLE employees;
-- Create the employees table
CREATE TABLE employees (
id INTEGER PRIMARY KEY,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
position VARCHAR(50),
salary DECIMAL(10, 2),
hired_at DATE,
bonus DECIMAL(10, 2),
commission DECIMAL(10, 2),
hours_worked INTEGER
);
-- Insert records into the employees table
INSERT INTO employees ( id, first_name, last_name, position, salary, hired_at, bonus, commission, hours_worked ) VALUES
(1, 'John', 'Doe', 'Manager', 50000.00, TO_DATE('2022-01-15','YYYY-MM-DD'), 5000.00, 2000.00, 45),
(2, 'Anna', 'Petrovich', 'Developer', 65000.00, TO_DATE('2022-05-20','YYYY-MM-DD'), 3000.00, 1500.00, 40),
(3, 'Helen', 'Semenova', 'HR Specialist', 45000.00, TO_DATE('2022-03-10','YYYY-MM-DD'), 2000.00, 1000.00, 35),
(4, 'Michael', 'Sergeev', 'Administrator', 40000.00, TO_DATE('2022-02-01','YYYY-MM-DD'), 1500.00, 500.00, 30),
(5, 'Svetlana', 'Vasilyeva', 'Marketer', 55000.00, TO_DATE('2022-06-15','YYYY-MM-DD'), 4000.00, 2000.00, 42),
(6, 'Dmitry', 'Kirillov', 'Director', 75000.00, TO_DATE('2022-04-05','YYYY-MM-DD'), 6000.00, 3000.00, 48),
(7, 'Olga', 'Aleksandrova', 'Economist', 50000.00, TO_DATE('2022-07-20','YYYY-MM-DD'), 3500.00, 1800.00, 38),
(8, 'Paul', 'Andreevich', 'System Engineer', 60000.00, TO_DATE('2022-08-10','YYYY-MM-DD'), 4500.00, 2500.00, 43),
(9, 'Alexey', 'Romanovich', 'QA Officer', 58000.00, TO_DATE('2022-09-01','YYYY-MM-DD'), 2500.00, 1200.00, 36),
(10, 'Katerina', 'Nikolaeva', 'Chief Accountant', 70000.00, TO_DATE('2022-10-15','YYYY-MM-DD'), 5500.00, 2800.00, 46);
COMMIT;
SELECT * FROM employees;
3.3.4. Создаем репликацию#
В клиенте, подключенном к базе, в контейнере dbvm-redos-pr выполняем команду:
-- dbvm-redos-pr (10.88.0.68)
-- Создаем объект репликации
CONNECT sys/manager as sysdba;
CREATE REPLICATION rep1
WITH '10.88.0.69',35001
FROM hh.employees TO hh.employees;
В клиенте, подключенном к базе, в контейнере dbvm-redos-by выполняем команду:
-- dbvm-redos-by (10.88.0.69)
-- Создаем объект репликации
CONNECT sys/manager as sysdba;
CREATE REPLICATION rep1
WITH '10.88.0.68',35001
FROM hh.employees TO hh.employees;
3.3.5. Запускаем репликацию#
В клиенте, подключенном к базе, в контейнере dbvm-redos-pr выполняем команды:
-- dbvm-redos-pr (10.88.0.68)
-- Запускаем репликацию
iSQL(sysdba)> alter replication rep1 start;
Alter success.
ДЕЛАЕМ ПРОВЕРКУ
В клиенте, подключенном к базе, в контейнере dbvm-redos-pr выполняем команды:
-- dbvm-redos-pr (10.88.0.68)
-- Проверяем данные отправителя:
iSQL(sysdba)> select * from v$repsender;
REP_NAME : REP1
START_FLAG : 0
NET_ERROR_FLAG : 0
XSN : 1475778
COMMIT_XSN : 1474713
STATUS : 1
SENDER_IP : 10.88.0.68
PEER_IP : 10.88.0.69
SENDER_PORT : 55076
PEER_PORT : 35001
READ_LOG_COUNT : 6
SEND_LOG_COUNT : 0
REPL_MODE : LAZY
ACT_REPL_MODE : LAZY
1 row selected.
-- dbvm-redos-pr (10.88.0.68)
-- Проверяем данные получателя (отсутствуют):
iSQL(sysdba)> select * from v$repreceiver;
No rows selected.
-- dbvm-redos-pr (10.88.0.68)
-- Проверяем данные по задержке репликации:
iSQL(sysdba)> select * from v$repgap;
REP_NAME : REP1
START_FLAG : 0
REP_LAST_SN : 1475778
REP_SN : 1475778
REP_GAP : 0
REP_GAP_SIZE : 0
READ_LFG_ID : 0
READ_FILE_NO : 0
READ_OFFSET : 1475778
В клиенте, подключенном к базе, в контейнере dbvm-redos-by выполняем команды:
-- dbvm-redos-by (10.88.0.69)
-- Проверяем данные отправителя (отсутствуют):
iSQL(sysdba)> select * from v$repsender;
No rows selected.
-- dbvm-redos-by (10.88.0.69)
-- Проверяем данные получателя:
iSQL(sysdba)> select * from v$repreceiver;
REP_NAME : REP1
MY_IP : 10.88.0.69
MY_PORT : 35001
PEER_IP : 10.88.0.68
PEER_PORT : 55076
APPLY_XSN : 1475778
INSERT_SUCCESS_COUNT : 0
INSERT_FAILURE_COUNT : 0
UPDATE_SUCCESS_COUNT : 0
UPDATE_FAILURE_COUNT : 0
DELETE_SUCCESS_COUNT : 0
DELETE_FAILURE_COUNT : 0
PARALLEL_ID : 0
SQL_APPLY_TABLE_COUNT : 0
APPLIER_INIT_BUFFER_USAGE : 0
1 row selected.
-- dbvm-redos-by (10.88.0.69)
-- Проверяем данные по задержке репликации (отсутствуют)
iSQL(sysdba)> select * from v$repgap;
No rows selected.
3.3.6. Добавление данных в реплицируюмую таблицу#
В клиенте, подключенном к базе, в контейнере dbvm-redos-pr выполняем команды:
-- dbvm-redos-pr (10.88.0.68)
-- Добавляем 1 строку в таблицу
CONNECT hh/hh;
-- Add a new employee to the database
INSERT INTO employees ( id, first_name, last_name, position, salary, hired_at, bonus, commission, hours_worked ) VALUES
(11, 'Tom', 'Jones', 'Developer', 52000.00, TO_DATE('2023-01-15','YYYY-MM-DD'), 3800, 1900, 33); -- OK
COMMIT;
-- dbvm-redos-pr (10.88.0.68)
-- Проверяем наличие новой строки в таблице
iSQL(sysdba)> set vertical on;
iSQL(sysdba)> select * from hh.employees where id = 11;
ID : 11
FIRST_NAME : Tom
LAST_NAME : Jones
POSITION : Developer
SALARY : 52000
HIRED_AT : 15-JAN-2023
BONUS : 3800
COMMISSION : 1900
HOURS_WORKED : 33
1 row selected.
В клиенте, подключенном к базе, в контейнере dbvm-redos-by выполняем команды:
-- dbvm-redos-by (10.88.0.69)
-- Проверяем наличие новой строки в таблице
iSQL(sysdba)> set vertical on;
iSQL(sysdba)> select * from hh.employees where id = 11;
ID : 11
FIRST_NAME : Tom
LAST_NAME : Jones
POSITION : Developer
SALARY : 52000
HIRED_AT : 15-JAN-2023
BONUS : 3800
COMMISSION : 1900
HOURS_WORKED : 33
1 row selected.
-- dbvm-redos-by (10.88.0.69)
-- Проверяем наличие новой строки по статистике приемника
iSQL(sysdba)> select * from v$repreceiver;
REP_NAME : REP1
MY_IP : 10.88.0.69
MY_PORT : 35001
PEER_IP : 10.88.0.68
PEER_PORT : 49418
APPLY_XSN : 1527137
INSERT_SUCCESS_COUNT : 1
INSERT_FAILURE_COUNT : 0
UPDATE_SUCCESS_COUNT : 0
UPDATE_FAILURE_COUNT : 0
DELETE_SUCCESS_COUNT : 0
DELETE_FAILURE_COUNT : 0
PARALLEL_ID : 0
SQL_APPLY_TABLE_COUNT : 0
APPLIER_INIT_BUFFER_USAGE : 0
1 row selected.
3.3.6. Останов репликации#
В клиенте, подключенном к базе, в контейнере dbvm-redos-pr выполняем команды:
-- dbvm-redos-pr (10.88.0.68)
-- Проверяем данные отправителя (отсутствуют):
iSQL(sysdba)> select * from v$repsender;
No rows selected.
-- Проверяем данные получателя (отсутствуют):
iSQL(sysdba)> select * from v$repreceiver;
No rows selected.
-- Проверяем данные по задержке репликации (отсутствуют):
iSQL(sysdba)> select * from v$repgap;
No rows selected.
В клиенте, подключенном к базе, в контейнере dbvm-redos-by выполняем команды:
-- dbvm-redos-by (10.88.0.69)
-- Проверяем данные отправителя (отсутствуют):
iSQL(sysdba)> select * from v$repsender;
No rows selected.
-- Проверяем данные получателя (отсутствуют):
iSQL(sysdba)> select * from v$repreceiver;
No rows selected.
-- Проверяем данные по задержке репликации (отсутствуют):
iSQL(sysdba)> select * from v$repgap;
No rows selected.
3.3.7. Удаление репликации#
В клиенте, подключенном к базе, в контейнере dbvm-redos-pr выполняем команду:
В клиенте, подключенном к базе, в контейнере dbvm-redos-by выполняем команду: