风哥教程参考DB2官方文档Financial Services Solutions、High Availability Guide等内容,详细介绍金融核心系统在DB2上的架构设计、表结构设计、事务管理、高可用方案。更多视频教程www.fgedu.net.cn
目录大纲
Part01-金融核心系统架构
1.1 金融系统特点
金融核心系统具有以下特点:
- 高并发:每日数百万甚至数千万笔交易
- 高可用:99.99%以上的可用性要求
- 数据一致性:ACID要求严格
- 安全性:数据加密、审计、权限控制
- 可追溯:完整的交易日志和审计
- 灾备要求:异地灾备、快速切换
1.2 系统架构设计
数据库层架构
- 采用HADR高可用架构
- 主备双机或多副本
- 读写分离设计
- 分库分表策略
- 异地灾备部署
1.3 存储架构设计
CREATE LARGE TABLESPACE ACCOUNT_TS
PAGESIZE 32K
MANAGED BY AUTOMATIC STORAGE
USING STOGROUP IBMSTOGROUP
EXTENTSIZE 64
PREFETCHSIZE 128
BUFFERPOOL BP32K
AUTORESIZE YES
INITIALSIZE 100G
MAXSIZE 1T;
# 创建索引表空间
CREATE LARGE TABLESPACE ACCOUNT_IDX_TS
PAGESIZE 32K
MANAGED BY AUTOMATIC STORAGE
USING STOGROUP IBMSTOGROUP
EXTENTSIZE 32
PREFETCHSIZE 64
BUFFERPOOL BP32K
AUTORESIZE YES
INITIALSIZE 50G
MAXSIZE 500G;
# 创建大对象表空间
CREATE LARGE TABLESPACE ACCOUNT_LOB_TS
PAGESIZE 32K
MANAGED BY AUTOMATIC STORAGE
USING STOGROUP IBMSTOGROUP
EXTENTSIZE 64
PREFETCHSIZE 128
BUFFERPOOL BP32K
FILE SYSTEM CACHING NO;
# 创建日志表空间
CREATE LARGE TABLESPACE TRANS_LOG_TS
PAGESIZE 8K
MANAGED BY AUTOMATIC STORAGE
USING STOGROUP IBMSTOGROUP
EXTENTSIZE 32
PREFETCHSIZE 64
BUFFERPOOL BP8K;
Part02-表结构设计
2.1 账户表设计
CREATE TABLE ACCOUNT (
ACCT_ID VARCHAR(32) NOT NULL,
CUST_ID VARCHAR(32) NOT NULL,
ACCT_TYPE VARCHAR(10) NOT NULL,
ACCT_STATUS VARCHAR(10) NOT NULL,
CURRENCY VARCHAR(3) NOT NULL,
BALANCE DECIMAL(18, 2) NOT NULL DEFAULT 0,
AVAILABLE_BALANCE DECIMAL(18, 2) NOT NULL DEFAULT 0,
FROZEN_AMOUNT DECIMAL(18, 2) NOT NULL DEFAULT 0,
OPEN_DATE DATE NOT NULL,
CLOSE_DATE DATE,
BRANCH_ID VARCHAR(10) NOT NULL,
CREATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT TIMESTAMP,
UPDATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT TIMESTAMP,
CONSTRAINT PK_ACCOUNT PRIMARY KEY (ACCT_ID)
) IN ACCOUNT_TS
INDEX IN ACCOUNT_IDX_TS;
# 创建索引
CREATE UNIQUE INDEX IDX_ACCOUNT_CUST ON ACCOUNT(CUST_ID, ACCT_TYPE) CLUSTER;
CREATE INDEX IDX_ACCOUNT_BRANCH ON ACCOUNT(BRANCH_ID, ACCT_STATUS);
# 创建账户余额历史表
CREATE TABLE ACCOUNT_BALANCE_HIST (
HIST_ID BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
ACCT_ID VARCHAR(32) NOT NULL,
BALANCE_BEFORE DECIMAL(18, 2) NOT NULL,
BALANCE_AFTER DECIMAL(18, 2) NOT NULL,
CHANGE_AMOUNT DECIMAL(18, 2) NOT NULL,
TRANS_ID VARCHAR(32) NOT NULL,
TRANS_TYPE VARCHAR(20) NOT NULL,
RECORD_TIME TIMESTAMP NOT NULL DEFAULT CURRENT TIMESTAMP,
CONSTRAINT PK_ACCOUNT_BALANCE_HIST PRIMARY KEY (HIST_ID)
) PARTITION BY RANGE (RECORD_TIME)
(
STARTING ‘2026-01-01’ ENDING ‘2026-12-31’ EVERY 1 MONTHS
);
# 创建索引
CREATE INDEX IDX_ACCT_BAL_HIST_ACCT ON ACCOUNT_BALANCE_HIST(ACCT_ID, RECORD_TIME DESC);
2.2 交易表设计
CREATE TABLE TRANSACTION (
TRANS_ID VARCHAR(32) NOT NULL,
TRANS_TYPE VARCHAR(20) NOT NULL,
ACCT_ID_FROM VARCHAR(32),
ACCT_ID_TO VARCHAR(32),
AMOUNT DECIMAL(18, 2) NOT NULL,
CURRENCY VARCHAR(3) NOT NULL,
TRANS_STATUS VARCHAR(10) NOT NULL,
FAIL_REASON VARCHAR(200),
REMARK VARCHAR(500),
CHANNEL VARCHAR(20) NOT NULL,
OPERATOR VARCHAR(32),
BRANCH_ID VARCHAR(10),
TRANS_TIME TIMESTAMP NOT NULL DEFAULT CURRENT TIMESTAMP,
CREATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT TIMESTAMP,
UPDATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT TIMESTAMP,
CONSTRAINT PK_TRANSACTION PRIMARY KEY (TRANS_ID)
) PARTITION BY RANGE (TRANS_TIME)
(
STARTING ‘2026-01-01’ ENDING ‘2026-12-31’ EVERY 1 DAY
);
# 创建索引
CREATE INDEX IDX_TRANS_ACCT_FROM ON TRANSACTION(ACCT_ID_FROM, TRANS_TIME DESC);
CREATE INDEX IDX_TRANS_ACCT_TO ON TRANSACTION(ACCT_ID_TO, TRANS_TIME DESC);
CREATE INDEX IDX_TRANS_STATUS ON TRANSACTION(TRANS_STATUS, TRANS_TIME);
# 创建交易明细表
CREATE TABLE TRANS_DETAIL (
DETAIL_ID BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,
TRANS_ID VARCHAR(32) NOT NULL,
ACCT_ID VARCHAR(32) NOT NULL,
DIRECTION VARCHAR(10) NOT NULL,
AMOUNT DECIMAL(18, 2) NOT NULL,
BALANCE_BEFORE DECIMAL(18, 2) NOT NULL,
BALANCE_AFTER DECIMAL(18, 2) NOT NULL,
CREATE_TIME TIMESTAMP NOT NULL DEFAULT CURRENT TIMESTAMP,
CONSTRAINT PK_TRANS_DETAIL PRIMARY KEY (DETAIL_ID)
) PARTITION BY RANGE (CREATE_TIME)
(
STARTING ‘2026-01-01’ ENDING ‘2026-12-31’ EVERY 1 DAY
);
# 创建索引
CREATE INDEX IDX_TRANS_DETAIL_TRANS ON TRANS_DETAIL(TRANS_ID);
CREATE INDEX IDX_TRANS_DETAIL_ACCT ON TRANS_DETAIL(ACCT_ID, CREATE_TIME DESC);
2.3 流水号生成
CREATE SEQUENCE SEQ_TRANS_ID
START WITH 1
INCREMENT BY 1
NO MAXVALUE
NO CYCLE
CACHE 1000;
# 创建流水号生成函数
CREATE OR REPLACE FUNCTION FN_GENERATE_TRANS_ID()
RETURNS VARCHAR(32)
LANGUAGE SQL
BEGIN ATOMIC
DECLARE v_timestamp VARCHAR(14);
DECLARE v_seq BIGINT;
DECLARE v_trans_id VARCHAR(32);
SET v_timestamp = TO_CHAR(CURRENT TIMESTAMP, ‘YYYYMMDDHH24MISS’);
SET v_seq = NEXT VALUE FOR SEQ_TRANS_ID;
SET v_trans_id = v_timestamp || LPAD(CAST(MOD(v_seq, 100000) AS VARCHAR(5)), 5, ‘0’);
RETURN v_trans_id;
END;
# 使用函数生成流水号
VALUES FN_GENERATE_TRANS_ID();
Part03-事务与并发控制
3.1 转账事务设计
CREATE OR REPLACE PROCEDURE SP_TRANSFER(
IN p_acct_from VARCHAR(32),
IN p_acct_to VARCHAR(32),
IN p_amount DECIMAL(18, 2),
IN p_currency VARCHAR(3),
IN p_remark VARCHAR(500),
IN p_channel VARCHAR(20),
OUT p_trans_id VARCHAR(32),
OUT p_result_code VARCHAR(10),
OUT p_result_msg VARCHAR(200)
)
LANGUAGE SQL
BEGIN
DECLARE v_balance_from DECIMAL(18, 2);
DECLARE v_balance_to DECIMAL(18, 2);
DECLARE v_acct_status_from VARCHAR(10);
DECLARE v_acct_status_to VARCHAR(10);
DECLARE v_sqlcode INTEGER;
DECLARE v_sqlstate CHAR(5);
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS EXCEPTION 1
v_sqlcode = DB2_RETURNED_SQLCODE,
v_sqlstate = RETURNED_SQLSTATE;
ROLLBACK;
SET p_result_code = ‘FAIL’;
SET p_result_msg = ‘SQL错误: ‘ || CAST(v_sqlcode AS VARCHAR(10)) || ‘, ‘ || v_sqlstate;
END;
SET p_result_code = ‘SUCCESS’;
SET p_result_msg = ‘转账成功’;
SET p_trans_id = FN_GENERATE_TRANS_ID();
START TRANSACTION;
SELECT BALANCE, ACCT_STATUS INTO v_balance_from, v_acct_status_from
FROM ACCOUNT WHERE ACCT_ID = p_acct_from WITH RS USE AND KEEP UPDATE LOCKS;
IF v_acct_status <> ‘NORMAL’ THEN
SIGNAL SQLSTATE ‘70001’ SET MESSAGE_TEXT = ‘转出账户状态异常’;
END IF;
IF v_balance_from < p_amount THEN
SIGNAL SQLSTATE '70002' SET MESSAGE_TEXT = '余额不足';
END IF;
SELECT BALANCE, ACCT_STATUS INTO v_balance_to, v_acct_status_to
FROM ACCOUNT WHERE ACCT_ID = p_acct_to WITH RS USE AND KEEP UPDATE LOCKS;
IF v_acct_status_to <> ‘NORMAL’ THEN
SIGNAL SQLSTATE ‘70003’ SET MESSAGE_TEXT = ‘转入账户状态异常’;
END IF;
INSERT INTO TRANSACTION (
TRANS_ID, TRANS_TYPE, ACCT_ID_FROM, ACCT_ID_TO, AMOUNT, CURRENCY,
TRANS_STATUS, REMARK, CHANNEL
) VALUES (
p_trans_id, ‘TRANSFER’, p_acct_from, p_acct_to, p_amount, p_currency,
‘PROCESSING’, p_remark, p_channel
);
UPDATE ACCOUNT
SET BALANCE = BALANCE – p_amount,
AVAILABLE_BALANCE = AVAILABLE_BALANCE – p_amount,
UPDATE_TIME = CURRENT TIMESTAMP
WHERE ACCT_ID = p_acct_from;
INSERT INTO ACCOUNT_BALANCE_HIST (
ACCT_ID, BALANCE_BEFORE, BALANCE_AFTER, CHANGE_AMOUNT,
TRANS_ID, TRANS_TYPE
) VALUES (
p_acct_from, v_balance_from, v_balance_from – p_amount, -p_amount,
p_trans_id, ‘TRANSFER_OUT’
);
UPDATE ACCOUNT
SET BALANCE = BALANCE + p_amount,
AVAILABLE_BALANCE = AVAILABLE_BALANCE + p_amount,
UPDATE_TIME = CURRENT TIMESTAMP
WHERE ACCT_ID = p_acct_to;
INSERT INTO ACCOUNT_BALANCE_HIST (
ACCT_ID, BALANCE_BEFORE, BALANCE_AFTER, CHANGE_AMOUNT,
TRANS_ID, TRANS_TYPE
) VALUES (
p_acct_to, v_balance_to, v_balance_to + p_amount, p_amount,
p_trans_id, ‘TRANSFER_IN’
);
UPDATE TRANSACTION
SET TRANS_STATUS = ‘SUCCESS’,
UPDATE_TIME = CURRENT TIMESTAMP
WHERE TRANS_ID = p_trans_id;
COMMIT;
END;
# 调用转账存储过程
CALL SP_TRANSFER(
‘ACCT001’, ‘ACCT002’, 1000.00, ‘CNY’, ‘测试转账’, ‘MOBILE’,
?, ?, ?
);
3.2 锁与隔离级别
UPDATE DATABASE CONFIGURATION FOR fgedb USING
LOCKLIST 10000
MAXLOCKS 50
LOCKTIMEOUT 30
DLCHKTIME 10000;
# 设置应用隔离级别
SET CURRENT ISOLATION = CS;
# 查看锁等待
SELECT
AGENT_ID,
APPL_NAME,
LOCK_OBJECT_TYPE,
LOCK_MODE,
LOCK_STATUS,
TABNAME
FROM TABLE(MON_GET_LOCKS(”, -2)) AS T;
# 查看死锁
SELECT
EVENT_TIMESTAMP,
PARTICIPANT_NO,
LOCK_NAME,
LOCK_MODE,
TABLE_SCHEMA,
TABLE_NAME
FROM TABLE(MON_GET_DEADLOCKS(”, -2)) AS T;
Part04-高可用与灾备
4.1 HADR配置
UPDATE DATABASE CONFIGURATION FOR fgedb USING
HADR_LOCAL_HOST primary.fgedu.net.cn
HADR_LOCAL_SVC 50000
HADR_REMOTE_HOST standby.fgedu.net.cn
HADR_REMOTE_SVC 50000
HADR_REMOTE_INST db2inst1
HADR_SYNCMODE NEARSYNC
HADR_TIMEOUT 120
HADR_PEER_WINDOW 300
LOGINDEXBUILD ON;
# 备库配置
UPDATE DATABASE CONFIGURATION FOR fgedb USING
HADR_LOCAL_HOST standby.fgedu.net.cn
HADR_LOCAL_SVC 50000
HADR_REMOTE_HOST primary.fgedu.net.cn
HADR_REMOTE_SVC 50000
HADR_REMOTE_INST db2inst1
HADR_SYNCMODE NEARSYNC
HADR_TIMEOUT 120
HADR_PEER_WINDOW 300
LOGINDEXBUILD ON;
# 启动HADR
# 备库
START HADR ON DATABASE fgedb AS STANDBY;
# 主库
START HADR ON DATABASE fgedb AS PRIMARY;
# 查看HADR状态
GET SNAPSHOT FOR HADR ON DATABASE fgedb;
# 手动切换
TAKE OVER HADR ON DATABASE fgedb;
4.2 备份策略
#!/bin/bash
BACKUP_DIR=”/db2/backup/full”
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE=”$BACKUP_DIR/backup_$DATE.log”
mkdir -p $BACKUP_DIR
echo “开始全量备份: $DATE” > $LOG_FILE
db2 “BACKUP DATABASE fgedb TO $BACKUP_DIR COMPRESS” >> $LOG_FILE 2>&1
if [ $? -eq 0 ]; then
echo “全量备份成功” >> $LOG_FILE
else
echo “全量备份失败” >> $LOG_FILE
fi
# 增量备份
db2 “BACKUP DATABASE fgedb TO $BACKUP_DIR INCREMENTAL COMPRESS”
# 归档日志配置
UPDATE DATABASE CONFIGURATION FOR fgedb USING
LOGARCHMETH1 DISK:/db2/archive_logs
LOGARCHMETH2 OFF
LOGPRIMARY 50
LOGSECOND 100
LOGFILSIZ 1024
SOFTMAX 100;
# 备份保留策略
find $BACKUP_DIR -name “*.001” -mtime +7 -delete
Part05-风哥经验总结与分享
5.1 金融系统设计要点
- 数据一致性优先,使用严格的事务控制
- 表设计考虑分区分表,便于扩容
- 索引设计要合理,避免过度索引
- 完整的审计日志,支持追溯
- 高可用架构,确保系统不中断
- 完善的备份和灾备方案
- 安全加固,数据加密
5.2 性能优化建议
| 优化项 | 建议 |
|---|---|
| 表分区 | 按时间分区,便于归档 |
| 缓冲池 | 大页表空间使用大缓冲池 |
| 事务 | 保持事务短小,避免长事务 |
| 锁 | |
| 日志 | 足够的日志空间,优化日志参数 |
5.3 运维要点
- 建立完善的监控告警体系
- 定期进行备份恢复演练
- 定期进行灾备切换演练
- 数据库参数定期review
- 定期清理历史数据
- 定期更新DB2补丁
- 建立变更管理流程
学习交流加群风哥微信: itpux-com
风哥Oracle/MySQL/PostgreSQL/Greenplum/DB2/Redis等数据库培训课程,10年一线实战经验,企业级培训,真正掌握数据库核心技术!
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
