Switchover后序列当前值不自动同步,因Data Guard仅复制数据文件和归档日志,SEQUENCE的CURRVAL/NEXTVAL状态驻留内存且备库只读不执行NEXTVAL,导致新主库序列值远小于表中实际最大ID,须手动用ALTER SEQUENCE increment by临时调整步长并推进至目标值后恢复步长为1。
主备角色互换后,sequence 当前值不会自动同步,必须手动重置,否则插入数据会报主键冲突或重复值错误。
为什么 Switchover 后序列号不一致
Oracle Data Guard 的 Switchover 只同步数据文件和归档日志,SEQUENCE 是内存+数据字典对象,其 CURRVAL 和 NEXTVAL 状态不随物理复制传递。原主库的序列可能已走到 12000,但新主库(原备库)上该序列仍停在 500——因为备库在只读/恢复模式下根本不会执行 NEXTVAL。
常见现象包括:
- 新主库执行
INSERT INTO t1(id, name) VALUES(seq_t1.nextval, 'test')报ORA-00001: unique constraint violated -
SELECT seq_t1.currval FROM dual报ORA-08002: sequence SEQ_T1.CURRVAL is not yet defined in this session - 表中已有最大 ID 是 11999,但
seq_t1.nextval返回 501
用 ALTER SEQUENCE increment by 调整当前值(不删重建)
这是最安全的方式:不删除序列,避免依赖它的触发器、包、视图失效,也不需要重新编译对象。
操作分三步,核心是利用步长(increment by)临时“倒退”再“跳到目标”:
- 查出表中当前最大 ID:
SELECT NVL(MAX(id), 0) FROM t1→ 假设得 11999 - 执行
ALTER SEQUENCE seq_t1 INCREMENT BY 11999 - seq_t1.nextval + 1(即让下一次NEXTVAL刚好等于 12000) - 调一次
SELECT seq_t1.nextval FROM dual,强制推进到目标值 - 立即还原步长:
ALTER SEQUENCE seq_t1 INCREMENT BY 1
示例(假设当前 seq_t1.nextval 是 500,表最大 id 是 11999):
SELECT seq_t1.nextval FROM dual; -- 返回 500 ALTER SEQUENCE seq_t1 INCREMENT BY 11500; -- 11999 - 500 + 1 = 11500 SELECT seq_t1.nextval FROM dual; -- 返回 12000 ALTER SEQUENCE seq_t1 INCREMENT BY 1;
检查与验证要点
重置后务必验证,不能只信 SQL 执行成功:
- 确认表中最大值:
SELECT MAX(id) FROM t1 - 确认序列下一次值:
SELECT seq_t1.nextval FROM dual(执行两次,看是否递增) - 测试插入:
INSERT INTO t1(id, name) VALUES(seq_t1.nextval, 'verify'),再查是否为 12001 - 注意:如果序列定义了
MINVALUE或CYCLE,调整前要先ALTER SEQUENCE ... NOCYCLE防止意外循环回绕
真正容易被忽略的是:序列重置必须在 Switchover 完成、新主库已 OPEN 且业务尚未写入前完成。一旦有应用开始用旧序列值插入,修复成本就从几条命令变成全量数据校验了。


















