目录
Oracle到OceanBase数据库迁移实践项目
项目概述
项目背景
本项目旨在将一个中等规模的Oracle数据库完整迁移至OceanBase数据库,包括数据结构、数据内容、存储过程、触发器等数据库对象,并确保迁移后的系统能够正常运行且性能达标。
项目目标
- 完成Oracle数据库到OceanBase的完整迁移
- 确保数据一致性和完整性
- 验证业务功能正常运行
- 达到或超越原有性能指标
- 建立可复用的迁移方法论
项目范围
- 数据库规模:100-500GB
- 表数量:200-500张
- 存储过程:50-100个
- 触发器:20-50个
- 并发用户:100-500
一、迁移可行性评估
1.1 源数据库调研
数据库基本信息收集
-- Oracle版本信息
SELECT * FROM v$version;
-- 数据库字符集
SELECT * FROM nls_database_parameters
WHERE parameter IN ('NLS_CHARACTERSET', 'NLS_NCHAR_CHARACTERSET');
-- 数据库大小
SELECT
SUM(bytes)/1024/1024/1024 AS total_size_gb
FROM dba_segments;
-- 表空间信息
SELECT
tablespace_name,
SUM(bytes)/1024/1024/1024 AS size_gb,
status
FROM dba_data_files
GROUP BY tablespace_name, status;
对象统计分析
-- 各类对象数量统计
SELECT object_type, COUNT(*) AS count
FROM dba_objects
WHERE owner NOT IN ('SYS', 'SYSTEM')
GROUP BY object_type
ORDER BY count DESC;
-- 大表识别(>1GB)
SELECT
owner,
segment_name,
segment_type,
bytes/1024/1024/1024 AS size_gb
FROM dba_segments
WHERE bytes > 1073741824
ORDER BY bytes DESC;
-- 分区表统计
SELECT
owner,
table_name,
partitioning_type,
partition_count
FROM dba_part_tables;
1.2 兼容性评估
数据类型兼容性检查
-- 检查特殊数据类型使用情况
SELECT
owner,
table_name,
column_name,
data_type
FROM dba_tab_columns
WHERE data_type IN (
'XMLTYPE', 'BFILE', 'ROWID',
'INTERVAL YEAR TO MONTH',
'INTERVAL DAY TO SECOND'
)
AND owner NOT IN ('SYS', 'SYSTEM');
SQL语法兼容性评估
- Oracle特有函数使用情况
- 层次查询(CONNECT BY)
- MODEL子句
- PIVOT/UNPIVOT操作
- 正则表达式函数
- 分析函数
存储过程兼容性分析
-- 存储过程复杂度分析
SELECT
owner,
name,
type,
line_count
FROM (
SELECT
owner,
name,
type,
MAX(line) AS line_count
FROM dba_source
WHERE owner NOT IN ('SYS', 'SYSTEM')
GROUP BY owner, name, type
)
WHERE line_count > 1000
ORDER BY line_count DESC;
1.3 风险评估矩阵
| 风险类别 | 风险项 | 风险等级 | 应对措施 |
|---|---|---|---|
| 数据类型兼容性 | XMLTYPE不支持 | 高 | 转换为CLOB存储 |
| SQL语法差异 | CONNECT BY查询 | 中 | 改写为WITH RECURSIVE |
| 存储过程 | 包体语法差异 | 中 | 逐个改写测试 |
| 性能 | 执行计划差异 | 中 | SQL调优 |
| 业务连续性 | 停机时间过长 | 高 | 采用增量同步 |
二、迁移方案设计
2.1 迁移架构设计
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Oracle DB │────>│ OMS工具 │────>│ OceanBase DB │
│ (源数据库) │ │ (迁移平台) │ │ (目标数据库) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 数据校验 │ │ 监控告警 │ │ 性能测试 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
2.2 迁移策略选择
迁移方式对比
| 迁移方式 | 停机时间 | 数据一致性 | 实施复杂度 | 适用场景 |
|---|---|---|---|---|
| 停机迁移 | 长(4-8小时) | 高 | 低 | 小型系统 |
| 增量迁移 | 短(30分钟) | 高 | 高 | 生产系统 |
| 双写方案 | 极短(5分钟) | 中 | 极高 | 核心系统 |
推荐方案:采用OMS增量迁移方案
2.3 迁移时间规划
三、结构迁移实施
3.1 目标环境准备
OceanBase集群部署
# 集群规划
# 3节点集群,每节点配置:
# CPU: 16核
# 内存: 64GB
# 磁盘: 1TB SSD
# 创建租户
CREATE TENANT migrate_tenant
RESOURCE_POOL_LIST = ('migrate_pool')
CHARACTER SET = 'UTF8MB4'
COLLATE = 'utf8mb4_general_ci';
# 创建数据库
CREATE DATABASE target_db;
3.2 对象转换规则
数据类型映射表
| Oracle数据类型 | OceanBase数据类型 | 转换说明 |
|---|---|---|
| VARCHAR2(n) | VARCHAR(n) | 直接映射 |
| NUMBER | DECIMAL | 精度保持 |
| DATE | DATETIME | 包含时间部分 |
| CLOB | TEXT | 大文本 |
| BLOB | BLOB | 二进制大对象 |
| XMLTYPE | TEXT | XML转文本 |
| TIMESTAMP | TIMESTAMP | 时间戳 |
约束转换处理
-- 主键约束
ALTER TABLE table_name ADD PRIMARY KEY (column_name);
-- 外键约束(需评估是否保留)
ALTER TABLE child_table
ADD CONSTRAINT fk_name
FOREIGN KEY (column_name)
REFERENCES parent_table(column_name);
-- 唯一约束
ALTER TABLE table_name ADD UNIQUE KEY (column_name);
-- 检查约束
ALTER TABLE table_name
ADD CONSTRAINT check_name
CHECK (condition);
3.3 结构迁移执行
使用OMS工具迁移结构
# 配置源端连接
oms-ctl datasource create \
--type=ORACLE \
--host=192.168.1.100 \
--port=1521 \
--sid=ORCL \
--username=migrate_user \
--password=xxx
# 配置目标端连接
oms-ctl datasource create \
--type=OCEANBASE \
--host=192.168.1.200 \
--port=2883 \
--tenant=migrate_tenant \
--username=root \
--password=xxx
# 创建结构迁移任务
oms-ctl project create \
--name=struct_migrate \
--type=STRUCT_MIGRATION \
--source=oracle_source \
--target=ob_target
四、全量数据迁移
4.1 数据迁移前准备
数据清理
-- 清理历史数据
DELETE FROM log_table WHERE create_time < ADD_MONTHS(SYSDATE, -12);
-- 清理无效数据
DELETE FROM temp_table WHERE status = 'INVALID';
-- 重建索引优化性能
ALTER INDEX idx_name REBUILD;
迁移批次规划
- 第一批:基础数据表(字典表、配置表)
- 第二批:业务主表
- 第三批:业务明细表
- 第四批:日志表、历史表
4.2 全量迁移执行
OMS全量迁移配置
{
"migration_config": {
"parallel_degree": 4,
"batch_size": 5000,
"checkpoint_interval": 10000,
"error_tolerance": 100,
"compression": true,
"validation": true
}
}
大表迁移优化
-- 分区并行迁移
SELECT /*+ PARALLEL(4) */ * FROM large_table PARTITION (p1);
-- 按时间范围分批
SELECT * FROM transaction_table
WHERE create_date BETWEEN '2023-01-01' AND '2023-06-30';
4.3 迁移监控
实时监控指标
-- OMS迁移进度监控
SELECT
task_name,
table_name,
total_rows,
migrated_rows,
ROUND(migrated_rows/total_rows*100, 2) AS progress_pct,
migrate_speed,
estimated_time
FROM oms_migration_progress
ORDER BY progress_pct;
五、增量同步配置
5.1 增量同步原理
Oracle (源端) OceanBase (目标端)
│ │
├──> Redo Log ──┐ │
│ ▼ │
│ LogMiner │
│ │ │
│ ▼ │
│ OMS │
│ │ │
│ ▼ │
│ Change Data │
│ │ │
└───────────────┴────────────────┘
Apply Changes
5.2 增量同步配置
源端配置
-- 开启归档日志
ALTER DATABASE ARCHIVELOG;
-- 开启补充日志
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
ALTER TABLE table_name ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;
-- 创建同步用户
CREATE USER sync_user IDENTIFIED BY password;
GRANT SELECT ANY TABLE TO sync_user;
GRANT SELECT_CATALOG_ROLE TO sync_user;
GRANT EXECUTE ON DBMS_LOGMNR TO sync_user;
OMS增量任务配置
# 创建增量同步任务
oms-ctl project create \
--name=incr_sync \
--type=INCREMENTAL_MIGRATION \
--source=oracle_source \
--target=ob_target \
--start-scn=12345678 \
--tables="schema1.*,schema2.table1"
5.3 增量同步监控
同步延迟监控
-- 监控同步延迟
SELECT
source_commit_time,
target_apply_time,
TIMESTAMPDIFF(SECOND, source_commit_time, target_apply_time) AS lag_seconds
FROM sync_monitor_table
ORDER BY source_commit_time DESC
LIMIT 10;
六、数据一致性验证
6.1 数据量验证
表级数据量对比
-- Oracle端统计
SELECT
owner,
table_name,
num_rows
FROM dba_tables
WHERE owner = 'APP_SCHEMA'
ORDER BY table_name;
-- OceanBase端统计
SELECT
table_schema,
table_name,
table_rows
FROM information_schema.tables
WHERE table_schema = 'APP_SCHEMA'
ORDER BY table_name;
6.2 数据内容验证
抽样验证脚本
import cx_Oracle
import pymysql
import hashlib
def verify_table_data(table_name, sample_rate=0.1):
"""
数据一致性验证函数
"""
# Oracle连接
ora_conn = cx_Oracle.connect('user/pass@oracle_db')
ora_cursor = ora_conn.cursor()
# OceanBase连接
ob_conn = pymysql.connect(host='ob_host', user='user',
password='pass', database='db')
ob_cursor = ob_conn.cursor()
# 抽样查询
sample_sql = f"""
SELECT * FROM {table_name}
SAMPLE({sample_rate * 100})
ORDER BY primary_key
"""
# 执行查询并比对
ora_cursor.execute(sample_sql)
ora_data = ora_cursor.fetchall()
ob_cursor.execute(sample_sql.replace('SAMPLE', 'ORDER BY RAND() LIMIT'))
ob_data = ob_cursor.fetchall()
# 计算数据指纹
ora_hash = hashlib.md5(str(ora_data).encode()).hexdigest()
ob_hash = hashlib.md5(str(ob_data).encode()).hexdigest()
return ora_hash == ob_hash
6.3 业务规则验证
关键业务指标对比
-- 财务数据汇总对比
-- Oracle
SELECT
DATE_FORMAT(trans_date, '%Y-%m') AS month,
SUM(amount) AS total_amount,
COUNT(*) AS trans_count
FROM transaction_table
GROUP BY DATE_FORMAT(trans_date, '%Y-%m');
-- OceanBase
SELECT
DATE_FORMAT(trans_date, '%Y-%m') AS month,
SUM(amount) AS total_amount,
COUNT(*) AS trans_count
FROM transaction_table
GROUP BY DATE_FORMAT(trans_date, '%Y-%m');
七、存储过程和触发器验证
7.1 存储过程改造
语法差异处理示例
Oracle原始存储过程:
CREATE OR REPLACE PROCEDURE calc_bonus(
p_emp_id IN NUMBER,
p_bonus OUT NUMBER
) AS
v_salary NUMBER;
v_performance NUMBER;
BEGIN
SELECT salary, performance_score
INTO v_salary, v_performance
FROM employees
WHERE emp_id = p_emp_id;
p_bonus := v_salary * v_performance * 0.1;
DBMS_OUTPUT.PUT_LINE('Bonus calculated: ' || p_bonus);
EXCEPTION
WHEN NO_DATA_FOUND THEN
p_bonus := 0;
DBMS_OUTPUT.PUT_LINE('Employee not found');
END;
/
OceanBase改造后:
DELIMITER //
CREATE PROCEDURE calc_bonus(
IN p_emp_id INT,
OUT p_bonus DECIMAL(10,2)
)
BEGIN
DECLARE v_salary DECIMAL(10,2);
DECLARE v_performance DECIMAL(5,2);
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET p_bonus = 0;
SELECT salary, performance_score
INTO v_salary, v_performance
FROM employees
WHERE emp_id = p_emp_id;
SET p_bonus = v_salary * v_performance * 0.1;
SELECT CONCAT('Bonus calculated: ', p_bonus) AS message;
END//
DELIMITER ;
7.2 触发器验证
触发器功能测试
-- 创建测试触发器
DELIMITER //
CREATE TRIGGER audit_trigger
AFTER INSERT ON orders
FOR EACH ROW
BEGIN
INSERT INTO audit_log (
table_name,
operation,
user_name,
operation_time,
new_data
) VALUES (
'orders',
'INSERT',
USER(),
NOW(),
JSON_OBJECT('order_id', NEW.order_id, 'amount', NEW.amount)
);
END//
DELIMITER ;
-- 验证触发器
INSERT INTO orders (order_id, amount) VALUES (1001, 500.00);
SELECT * FROM audit_log WHERE table_name = 'orders';
7.3 功能测试清单
| 测试项 | 测试内容 | 预期结果 | 实际结果 | 状态 |
|---|---|---|---|---|
| 存储过程-计算类 | calc_bonus | 正确计算奖金 | ✓ | 通过 |
| 存储过程-批处理 | batch_process | 批量处理成功 | ✓ | 通过 |
| 触发器-审计 | audit_trigger | 记录审计日志 | ✓ | 通过 |
| 触发器-级联更新 | cascade_update | 级联更新成功 | ✓ | 通过 |
| 函数-自定义函数 | custom_function | 返回正确结果 | ✓ | 通过 |
八、性能测试与优化
8.1 性能基准测试
测试场景设计
| 场景名称 | 并发用户 | 事务类型 | TPS目标 | 响应时间要求 |
|---|---|---|---|---|
| OLTP混合 | 100 | 读写混合 | 5000 | <100ms |
| 批量查询 | 50 | 只读 | 10000 | <50ms |
| 批量写入 | 20 | 只写 | 2000 | <200ms |
| 复杂查询 | 10 | 分析查询 | 100 | <5s |
Sysbench测试脚本
# 准备测试数据
sysbench oltp_common \
--mysql-host=ob_host \
--mysql-port=2883 \
--mysql-user=test \
--mysql-password=test \
--mysql-db=sbtest \
--table-size=1000000 \
--tables=10 \
prepare
# 运行OLTP测试
sysbench oltp_read_write \
--mysql-host=ob_host \
--mysql-port=2883 \
--mysql-user=test \
--mysql-password=test \
--mysql-db=sbtest \
--table-size=1000000 \
--tables=10 \
--threads=100 \
--time=300 \
--report-interval=10 \
run
8.2 SQL性能优化
慢查询分析
-- 查找慢查询
SELECT
query,
exec_count,
avg_exec_time,
max_exec_time,
total_exec_time
FROM v$sql_audit
WHERE avg_exec_time > 1000 -- 超过1秒
ORDER BY avg_exec_time DESC
LIMIT 20;
索引优化建议
-- 分析表统计信息
ANALYZE TABLE table_name;
-- 查看执行计划
EXPLAIN SELECT * FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-01-31'
AND status = 'COMPLETED';
-- 创建优化索引
CREATE INDEX idx_order_date_status
ON orders(order_date, status);
8.3 系统参数优化
OceanBase参数调优
-- 内存相关参数
ALTER SYSTEM SET memory_limit = '50G';
ALTER SYSTEM SET memory_limit_percentage = 80;
-- SQL执行相关
ALTER SYSTEM SET parallel_servers_target = 64;
ALTER SYSTEM SET parallel_max_servers = 128;
-- 缓存优化
ALTER SYSTEM SET ob_plan_cache_percentage = 20;
ALTER SYSTEM SET ob_plan_cache_evict_high_percentage = 90;
-- 日志相关
ALTER SYSTEM SET max_string_print_length = 5000;
ALTER SYSTEM SET enable_sql_audit = true;
8.4 性能对比报告
性能测试结果对比
| 指标项 | Oracle | OceanBase | 提升比例 |
|---|---|---|---|
| TPS (OLTP) | 4500 | 5200 | +15.6% |
| QPS (查询) | 8000 | 9500 | +18.8% |
| 平均响应时间 | 120ms | 95ms | -20.8% |
| P99响应时间 | 500ms | 400ms | -20.0% |
| CPU使用率 | 65% | 55% | -15.4% |
| 内存使用率 | 70% | 60% | -14.3% |
九、切换上线方案
9.1 切换前检查清单
- 数据同步延迟 < 1秒
- 所有功能测试通过
- 性能测试达标
- 回滚方案准备就绪
- 监控告警配置完成
- 应用配置更新准备
- 运维团队待命
- 业务部门通知
9.2 切换步骤
9.3 回滚方案
快速回滚流程
- 停止应用服务
- 将数据库连接切回Oracle
- 启动应用服务
- 验证服务正常
- 分析问题原因
数据回滚(如需要)
# 使用备份恢复Oracle数据
rman target /
RESTORE DATABASE;
RECOVER DATABASE;
ALTER DATABASE OPEN;
十、项目总结
10.1 项目成果
关键指标达成
- 迁移规模:成功迁移 350GB 数据
- 对象数量:迁移 420 张表,85 个存储过程,35 个触发器
- 停机时间:实际停机 25 分钟(目标 30 分钟内)
- 数据一致性:100% 数据验证通过
- 性能提升:整体性能提升 15-20%
10.2 经验教训
成功经验
- 充分的前期评估:详细的兼容性分析避免了迁移中的重大问题
- 增量同步方案:大幅减少了停机时间
- 自动化工具:OMS工具提高了迁移效率
- 分批迁移策略:降低了迁移风险
问题与改进
- 存储过程改造耗时:建议提前建立语法转换规则库
- 性能测试不充分:应增加更多业务场景测试
- 监控告警延迟:需要实时监控系统支持
10.3 最佳实践建议
-
评估阶段
- 使用自动化工具进行兼容性扫描
- 建立完整的对象清单和依赖关系图
- 进行POC验证关键技术点
-
迁移阶段
- 采用并行迁移提高效率
- 设置合理的检查点便于断点续传
- 保持源库和目标库的监控
-
验证阶段
- 建立自动化验证脚本
- 进行全面的功能和性能测试
- 保留足够的并行运行期
-
运维阶段
- 建立专门的运维手册
- 配置完善的监控告警
- 定期进行性能分析和优化
10.4 后续规划
-
持续优化
- SQL性能持续调优
- 索引策略优化
- 参数调整
-
功能增强
- 利用OceanBase分布式特性
- 实现读写分离
- 部署多地多中心
-
知识沉淀
- 编写迁移工具和脚本
- 建立迁移知识库
- 培训运维团队
附录
A. 常用脚本和工具
数据验证脚本
#!/usr/bin/env python3
# data_validation.py
import concurrent.futures
import hashlib
from datetime import datetime
class DataValidator:
def __init__(self, source_conn, target_conn):
self.source = source_conn
self.target = target_conn
def validate_table(self, table_name):
"""验证单表数据"""
# 行数对比
source_count = self.get_row_count(self.source, table_name)
target_count = self.get_row_count(self.target, table_name)
# 数据抽样对比
sample_match = self.compare_sample_data(table_name)
# 主键完整性
pk_complete = self.check_primary_keys(table_name)
return {
'table': table_name,
'source_count': source_count,
'target_count': target_count,
'count_match': source_count == target_count,
'sample_match': sample_match,
'pk_complete': pk_complete,
'validation_time': datetime.now()
}
B. 监控指标配置
# prometheus_rules.yml
groups:
- name: database_migration
rules:
- alert: HighReplicationLag
expr: replication_lag_seconds > 5
for: 5m
labels:
severity: warning
annotations:
summary: "High replication lag detected"
- alert: DataValidationFailed
expr: data_validation_success == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Data validation failed"
C. 问题处理记录
| 问题描述 | 原因分析 | 解决方案 | 处理结果 |
|---|---|---|---|
| XMLTYPE迁移失败 | OceanBase不支持 | 转换为CLOB | 成功 |
| 存储过程编译错误 | 语法差异 | 手动改写 | 成功 |
| 增量同步延迟大 | 网络带宽不足 | 增加带宽 | 成功 |
| 索引创建失败 | 函数索引不支持 | 改为普通索引 | 成功 |
1954

被折叠的 条评论
为什么被折叠?



