TimesTen 数据库复制学习:7. 管理Active Standby Pair(无缓存组)

Active Standby Pair是TimesTen复制的一种固定模式,就是1个active到1个standby,再到0个或127个subscriber,如下图:

TimesTen 数据库复制学习:7. 管理Active Standby Pair(无缓存组)_第1张图片

配置 Active Standby Pair (不带缓存组)

大致步骤如下:
1. 创建数据库
2. 使用CREATE ACTIVE STANDBY PAIR创建复制
3. 调用Call ttRepStateSet('ACTIVE'),将active数据库的角色设为ACTIVE
4. 调用Call ttRepStart, 启动复制代理
5. 在active数据库中创建用户(用户名建议为repadmin),并赋予ADMIN权限
6. 克隆active数据库到standby数据库
7. 在standby数据库启动复制代理
8. 等待standby的角色自动变为STANDBY. (call ttrepstateget)
9. 克隆standby到subscriber数据库,如果有的话
10. 在subscriber数据库上启动复制代理

从active数据库的错误中恢复

当standby 可用时的恢复

当复制是return receipt 或 异步复制时

  1. 停止失效数据库的复制代理
  2. 将standby数据库角色设为ACTIVE。(ttRepStateSet(‘ACTIVE’))
  3. 在新的active数据库中,将原来的active设为失效。(ttRepStateSave(‘FAILED’, ‘failed_database’,’host_name’))
    这一步是必要的,因为正常情况下,只有standby才能向subscriber复制,而此时,我们必须让active向subscriber复制
  4. 删除失效的active数据库。(ttdestroy failed_database)
  5. 通过新的active克隆一个新的standby
  6. 在新的standby上启动复制代理
  7. 新的standby与active同步后,会接管向subscriber的复制任务
  8. 拓扑恢复正常,只不过此时active和standby调换了角色

实验过程如下:
首先设置一个active,standby和subscriber,过程可参见TimesTen 数据库复制学习:2. 配置Active Standby Pair ,确保三个库的状态分别为ACTIVE, STANDBY和IDLE。

master1> call ttrepstop; <- 停止active数据库上的复制代理,模拟其失效

master2> call ttRepStateSet('ACTIVE');
master2> call ttRepStateGet;
< ACTIVE, NO GRID >
1 row found.
master2> call ttRepStateSave('FAILED', 'master1','timesten-hol');
master2> @insert2

INSERT INTO employees VALUES
    ( 203,
    'Judy',
    'Fox',
    'JFOX',
    '603-123-7777',
    TO_DATE('17-AUG-1997', 'dd-MON-yyyy'),
    'MK_REP',
    6000,
    NULL,
    201,
    20
    );
1 row inserted. <- 此时active暂时接管了向subscriber的复制

subscriber1> select * from employees;
< 203, Judy, Fox, JFOX, 603-123-7777, 1997-08-17 00:00:00, MK_REP, 6000, <NULL>, 201, 20 >
1 rows found.

[oracle@timesten-hol ~]$ ttdestroy master1

[oracle@timesten-hol ~]$ ttRepAdmin -duplicate -from master2 -host $(hostname) -uid repadmin -pwd timesten master1

master1> call ttrepstart;
master1> call ttrepstateget;
< STANDBY, NO GRID > <-之前失效的active数据库变为standby
1 row found.

master2> @insert2

INSERT INTO employees VALUES
    ( 203,
    'Judy',
    'Fox',
    'JFOX',
    '603-123-7777',
    TO_DATE('17-AUG-1997', 'dd-MON-yyyy'),
    'MK_REP',
    6000,
    NULL,
    201,
    20
    );
1 row inserted. <- 在新的active上插入数据后,新的standby,subscriber都可以接受到数据,此时,standby重新接管了向subscriber的复制

master1> select count(*) from employees where employee_id = 203; < 1 > 1 row found. subscriber1> select count(*) from employees where employee_id = 203;
< 1 >
1 row found.

当复制是return twosafe时

  1. 将standby数据库角色设为ACTIVE。(ttRepStateSet(‘ACTIVE’))
  2. 在新的active数据库中,将原来的active设为失效。(ttRepStateSave(‘FAILED’, ‘failed_database’,’host_name’))
  3. 连接到之前失效的active数据库,自动启动恢复;如果恢复失败,则从新的active克隆,之后的过程与return receipt和异步相同。
  4. 将standby数据库角色设为ACTIVE。(ttRepStateSet(‘ACTIVE’))
  5. 在新的standby上启动复制代理

当新的standby同步后,会重写接管向subscriber复制的任务。

实验过程如下:
首先设置一个active,standby和subscriber,过程可参见TimesTen 数据库复制学习:2. 配置Active Standby Pair ,确保三个库的状态分别为ACTIVE, STANDBY和IDLE;以及复制传输策略为TWOSAFE。

master1> call ttrepstop; <- 停止active数据库上的复制代理,模拟其失效;

master2> call ttRepStateSet('ACTIVE');
master2> call ttRepStateGet;
< ACTIVE, NO GRID >
1 row found.

其实如果不停止,若强制把standby提升为ACTIVE,之前的active也会自动变为STANDBY。
[oracle@timesten-hol ~]$ ttRepAdmin -duplicate -from master2 -host $(hostname) -uid repadmin -pwd timesten master1

master1> call ttrepstart;
master1> call ttrepstateget;
< STANDBY, NO GRID > <-之前的active数据库自动变为standby
1 row found.

master1> call ttrepstateget;
< STANDBY, NO GRID >

下略

恢复到先前的节点

前述当active失效时,standby接管称为新的active,过程称为failover,如果需要failback,可以参见后面一节:对调active和standby数据库的角色

从standby数据库的错误中恢复

  1. 检测到standby故障
  2. 如果是TWOSAFE模式,standby故障将影响active数据库交易的提交,这时可以使用ttRepSyncSet( null, null, 2)设置本地提交。
  3. 在active数据库中调用ttRepStateSave(‘FAILED’,’standby_database’,’host_name’)将standby标记为失效。此时active接管了向subscriber的复制任务
  4. 禁止standby数据库复制代理的自动启动(如果设置了的话)
  5. 连接到standby数据库启动自动恢复,如果恢复失败,则从active克隆
  6. 启动standby数据库的复制代理

实验如下:

master2> call ttrepstop; <- 模拟standby故障

master1> call ttRepStateSave('FAILED','master2','timesten-hol');

master1> @insert1

INSERT INTO employees VALUES
    ( 202,
    'Pat',
    'Fay',
    'PFAY',
    '603-123-7777',
    TO_DATE('17-AUG-1997', 'dd-MON-yyyy'),
    'MK_REP',
    6000,
    NULL,
    201,
    20
    );
1 row inserted.

此时standby失效,active接管了向subscriber复制的任务

subscriber1> @s

select * from employees;
< 202, Pat, Fay, PFAY, 603-123-7777, 1997-08-17 00:00:00, MK_REP, 6000, <NULL>, 201, 20 >
1 row found.

恢复standby
master2> call ttrepstart;
master2> call ttrepstateget;
< STANDBY, NO GRID >
1 row found.

master1> @insert2

确认master2和subscriber都接收到了数据。

active和standby数据库同时错误时的恢复

称为dual failure或double failure。如以下的情形:
* standby失效,在standby恢复前或standby与active完全同步前,active又失效
* active失效,standby变为active,然后在恢复过程完成前,新的active又试失效

在两种情形中,subscriber都比standby具有更新的数据。

可以选择从active恢复,或从standby恢复,取决于哪个库的数据最新。

从active数据库恢复

  1. 连接到失效的active,触发自动恢复
  2. 确认复制代理已启动
  3. 设置角色为ACTIVE。(ttRepStateSet(‘ACTIVE’))
  4. 接下来介绍克隆等操作了

从standby数据库恢复(此处没有读懂)

  1. 连接到失效的standby,触发自动恢复
  2. 确保复制代理未启动
  3. 删除复制配置(DROP ACTIVE STANDBY PAIR)
  4. 重新创建复制配置(CREATE ACTIVE STANDBY PAIR)
  5. ttRepStateSet(‘ACTIVE’)设置master数据库的角色为active
  6. 在新的standby上启动复制代理

从subscriber数据库的错误中恢复

比较简单,可以有两种方法:
1. 连接subscriber数据库,让其自动从日志恢复,然后自动与其源数据库同步
2. 重新从standby克隆到subscriber,如果standby不可用,则从active克隆

对调active和standby数据库的角色

通常用于failover之后的failback,步骤如下:
1. 停止应用对数据库的更新
2. 调用ttRepSubscriberWait 确保所有active数据库的更新已同步到standby。也即两个数据库是完全同步的(返回值为0x00)
3. 停止active数据库的复制代理
4. 在active数据库调用ttRepDeactivate,将数据库状态置为IDLE
5. 调用ttRepStateSet('ACTIVE')将standby角色提升为ACTIVE
6. 在之前的active数据库中启动复制代理
7. 调用ttRepStateGet确认之前的active数据库的状态变为STANDBY
8. 恢复应用

测试如下:

master2> call ttRepSubscriberWait(NULL, NULL, 'master1', 'timesten-hol', 10);
< 00 >
1 row found. <- 从master2到master1的复制完全同步

说明:对于ASP复制,前面两个参数设成NULL即可,因为ASP复制只有一个DataStore级别的复制schema,即_ACTIVESTANDBY,owner是TTREP。

Command> SELECT REPLICATION_NAME, REPLICATION_OWNER FROM TTREP.REPLICATIONS;
< _ACTIVESTANDBY                 , TTREP                           >
1 row found.


master2> call ttrepstop;
master2> call ttRepDeactivate;
master2> call ttRepStateGet;
< IDLE, NO GRID >
1 row found.

master1> call ttRepStateSet('ACTIVE');
master1> call ttRepStateGet;
< ACTIVE, NO GRID >
1 row found.

master2> call ttRepStart;
master2> call ttRepStateGet;
< IDLE, NO GRID >
1 row found.
master2> call ttRepStateGet;
< STANDBY, NO GRID >
1 row found.

master1> @insert1
master1> select count(*) from employees;
< 2 >
1 row found.

确认master2和subscriber1上的数据条数也是为1

检查双active数据库

dual active和网络中断导致的split brain很类似,会造成数据的不一致。
以下我们模拟以下dual active的场景, 假设之前有一个正常运作的ASP:

master2> call ttrepstop;
master2> call ttrepstateset('active');
master2> call ttrepstateget;
< ACTIVE, NO GRID >
1 row found.

master1> call ttrepstateget;
< ACTIVE, NO GRID >
1 row found.

此时,两个库的状态都是ACTIVE,更危险的是,两个库还都可以更新

master1> @insert1

INSERT INTO employees VALUES
    ( 202,
    'Pat',
    'Fay',
    'PFAY',
    '603-123-7777',
    TO_DATE('17-AUG-1997', 'dd-MON-yyyy'),
    'MK_REP',
    6000,
    NULL,
    201,
    20
    );
1 row inserted.
master1> @s

select * from employees;
< 202, Pat, Fay, PFAY, 603-123-7777, 1997-08-17 00:00:00, MK_REP, 6000, <NULL>, 201, 20 >
1 row found.

master2> @insert2

INSERT INTO employees VALUES
    ( 203,
    'Judy',
    'Fox',
    'JFOX',
    '603-123-7777',
    TO_DATE('17-AUG-1997', 'dd-MON-yyyy'),
    'MK_REP',
    6000,
    NULL,
    201,
    20
    );
1 row inserted.
master2> @s

select * from employees;
< 203, Judy, Fox, JFOX, 603-123-7777, 1997-08-17 00:00:00, MK_REP, 6000, <NULL>, 201, 20 >
1 row found.

当网络恢复后,TimesTen会自动的判断哪个数据库比较新,由于我们的例子中,standby即master2是最后插入数据的,因此其保留ACTIVE的状态。
不是最新的数据库被置为无效,并且所有的连接被端口。当重新连接此standby时,如果其上没有未复制到对方的交易,那么其就自动成为STANDBY;如果存在未复制的交易,如我们以下的例子,则其状态被置为IDLE。或者你放弃掉此数据,然后从active数据库克隆,或者先手工补齐此数据,然后再从active数据库克隆。

master2> call ttrepstart;
master2> call ttrepstateget;
< ACTIVE, NO GRID >
1 row found.

master1> call ttrepstateget;
  994: Data store connection terminated. Please reconnect.
The command failed.

disconnect master1;
Disconnecting...
[oracle@timesten-hol ~]$ ttisql master1
Command> call ttrepstateget;
< IDLE, NO GRID >
1 row found.

你可能感兴趣的:(timesten,数据库复制)