简介:《金融数据库规范运维》是一份面向金融行业数据库管理员及运维团队的实战型PDF资料,聚焦数据库运维从稳态向敏态转型中的规范化方法论。内容涵盖双态运维理念(ITIL+DevOps)、规范建设指南、主备切换等复杂操作流程,以及通过工作流原子化、标准原子库、脚本化落地的具体路径;同时涉及容灾策略、告警处理、值班巡检、性能优化与应急预案,并梳理事件库、告警库、变更库的信息归档方式,以及值班岗、专家岗、远端专家团的分工协同机制。资源为单个PDF文件,大小2.4MB,可直接阅读或打印,适合团队内部培训、运维流程梳理及新员工入门学习。已有68人学习,内容结构清晰,既有理论框架又有实操示例,对提升数据库运维规范化水平、减少人工失误具有较高参考价值。
1. 金融数据库为什么必须和普通运维分开写
凌晨一点,一条改表结构的变更在生产库上执行到一半,连接数被打满,整条入库链路全部阻塞。在普通业务系统里,这叫“运维翻车”;在金融系统里,翻车之后要面对的不只是恢复数据,还有变更审批、操作留痕、责任回溯这一整套事前没人提、事后全部要补齐的流程。金融数据库规范运维这一类文档要解决的,正是把“对的做法”固定成流程:账号权限怎么分、备份怎么验证、变更怎么审批、巡检怎么落库。适合金融或强监管行业的 DBA、运维工程师,也适合刚接手生产环境、想从“凭感觉运维”切换到“按规范运维”的团队。
2. 账号与权限规范:最小权限的落地检查
2.1 账号矩阵:谁、用什么、能做什么
金融库和普通业务库在账号管理上最大的差别,不是权限种类,而是“申请、审批、发放、回收”这条链路有没有闭环。普通库经常是开发要个账号,DBA 顺手一建,先用着,半年后这个人离职了,账号还留在库里。规范运维的第一步,是先做一张账号矩阵,把每一类账号的归属讲清楚。
| 账号类型 | 归属方 | 典型用途 | 默认权限边界 |
|---|---|---|---|
| 应用账号 | 应用系统 | 业务读写 | 只允许访问本应用相关 schema |
| 运维账号 | DBA | 日常巡检、变更 | 不开放 delete/truncate,部分环境只读 |
| 开发账号 | 研发团队 | 测试验证 | 仅限测试环境,禁止生产 |
| 审计账号 | 审计/合规 | 查询审计日志 | 只读,单独网络出口 |
这张表不是贴在墙上的,要落到数据库里可查。常见做法是建一个独立的db_meta库,用 DDL 记录每张表的归属应用、等级、允许访问的账号清单,再在数据库侧做白名单校验。账号申请走工单系统,工单号写进账号备注,后续回收时按工单核对,谁批的、谁建的、何时到期,都有据可查。
2.2 最小权限的检查 SQL:从垃圾授权里捞违规
权限规范不能只靠“下次注意”,要定期扫一遍现有授权。以 MySQL 为例,我一般会把所有账号的权限捞出来,和账号矩阵做对比:
-- 找出拥有 SUPER 或 ALL PRIVILEGES 的账号 SELECT user, host, 'super/root' AS priv_type FROM mysql.user WHERE super_priv = 'Y' OR all_priv = 'Y' UNION ALL -- 找出授权了 GRANT OPTION 的账号 SELECT user, host, 'with_grant_option' AS priv_type FROM mysql.user WHERE grant_priv = 'Y' UNION ALL -- 找出全局 DELETE 权限的账号 SELECT user, host, 'global_delete' AS priv_type FROM mysql.user WHERE delete_priv = 'Y'; -- 列出当前所有连接来源和用户,核对是否存在过期账号 SELECT user, host, db, command, time, state FROM information_schema.processlist WHERE user NOT IN ('event_scheduler', 'system user') ORDER BY user, host;这段 SQL 前半部分扫的是“静态授权”,后半部分抓的是“动态运行”时的真实连接。静态授权里最常翻车的是GRANT OPTION,一个普通开发账号被加上WITH GRANT OPTION之后,它就具备了给其他账号授权的权力,等于绕过了审批流。动态连接列表则用来发现僵尸账号:有账号在跑,但账号矩阵里找不到归属人,这类账号要立即回收。
注意,mysql.user表里的权限是全局级,数据库级和表级权限还要看mysql.db和mysql.tables_priv。扫完授权后,要按“账号矩阵表”倒着再查一遍:矩阵里登记了的账号,实际库里是否存在;库里存在的账号,矩阵里有没有记录。两边对不上,要么补录,要么回收。
2.3 连接池与账号复用:一个经常被忽略的隐性权限源
很多团队会在连接池和数据库同步工具上偷懒,用同一个高权限账号连接所有库。应用层连接池通常配置为多个应用共享一个账号,这个账号往往拥有跨库的查询权限。从“能跑”的角度看没问题,但从规范的角度看,一旦某个应用被注入,攻击面直接覆盖所有共享该账号的库。
我见过的折中做法是:每个应用至少独立账号,连接串里的账号密码不进配置文件,统一放到配置中心,走密钥管理系统下发。数据库侧则做 IP 白名单和网络策略,限制该账号只能从应用服务器所在网段发起连接。同步工具同理,数据同步账号只授予SELECT和REPLICATION SLAVE,不授予写权限,写操作必须走应用账号。
这里还要注意密码策略。金融环境的密码通常要求定期轮换,但轮换不能“一把梭”——以为改了数据库账号密码就行,结果连接池缓存了旧连接,应用半夜报连接失败,这种事故在变更窗口里太常见了。正确顺序是先改连接池配置或密钥管理系统,再在数据库侧改密码,中间留五分钟的缓冲,避免两端不同步导致服务中断。
3. 备份与恢复验证:把“备份过”变成“能恢复”
3.1 备份策略分层:物理备份、逻辑备份与归档
备份是金融数据库运维里最容易被“假象”欺骗的环节。日志显示每天备份成功,就以为数据安全了,等真正要恢复才发现备份文件是坏的、或者备份了但没有包含归档日志。规范里通常会做三层备份:物理全备、逻辑备份、归档日志备份。
| 层级 | 频率 | 用途 | 常见工具 |
|---|---|---|---|
| 物理全备 | 每日一次 | 快速恢复整个实例 | xtrabackup、RMAN |
| 逻辑备份 | 每周一次 | 单表/单库恢复、数据抽取 | mysqldump、pg_dump |
| 归档日志 | 实时/准实时 | 恢复到任意时间点 | binlog、归档 WAL |
物理备份解决“能不能起来”,逻辑备份解决“能不能捞数据”,归档日志解决“恢复点能精确到什么时间”。只做逻辑备份的团队,恢复 500G 的大库可能要十几个小时,业务等不起;只做物理备份的团队,误删了一张表,得先恢复整个实例再捞表;两者都做但归档日志没接,恢复点就只能停在全备时刻。三层配合才是完整的策略。
备份文件本身也要做异地存放。同机房的两台机器,一台着火全部玩完;同城双机房是底线,异地灾备是加分项。存放时注意备份文件的校验和,不只是传输校验,还要定期把备份文件拿出来做一次恢复演练,确认文件本身没有默默损坏。
3.2 恢复演练脚本:每月一次,用真实步骤验证
备份规范写得再漂亮,恢复不了就是废纸。我见过很多团队只在“出大事”时才做恢复,结果恢复手册和实际环境差了两三个版本,手册里写的路径根本不存在。更可靠的做法是每月选一个非生产实例,把最近一次备份文件完整恢复一遍,然后跑一个基于真实业务的验收脚本:
#!/bin/bash # 每月恢复演练:从物理备份恢复一个实例,再校验恢复后的数据可用性 BACKUP_DIR=/backup/$(date +%Y%m%d) TARGET_DIR=/restore_test/data TARGET_PORT=3307 # 1. 解包并准备数据目录 mkdir -p "$TARGET_DIR" xtrabackup --prepare --target-dir="$BACKUP_DIR" 2>&1 xtrabackup --copy-back --target-dir="$BACKUP_DIR" --datadir="$TARGET_DIR" # 2. 以新端口启动恢复后的实例,不干扰生产 mysqld --datadir="$TARGET_DIR" --port=$TARGET_PORT \ --socket=/tmp/restore_3307.sock --skip-networking & # 3. 等待实例就绪并校验关键表行数 for i in $(seq 1 30); do if mysqladmin --socket=/tmp/restore_3307.sock ping >/dev/null 2>&1; then break fi sleep 2 done # 4. 校验核心表行数和最新一笔交易时间 mysql --socket=/tmp/restore_3307.sock -e " SELECT 'orders' AS tbl, COUNT(1) AS cnt, MAX(create_time) AS latest FROM orders UNION ALL SELECT 'users', COUNT(1), MAX(update_time) FROM users; "这里的--prepare是把 xtrabackup 的物理备份做前滚恢复,属于恢复前的必需步骤;--copy-back把数据拷贝到新的数据目录。恢复出来的实例用独立端口和--skip-networking启动,只允许本机 socket 连接,避免恢复实例暴露到网络里。
脚本最后一步校验的不是“实例能启动”,而是“业务所依赖的数据在不在”。我一般会把线上最核心的三张表写死进脚本,行数变化超过阈值就报错。这个验证逻辑很关键:恢复演练的目的不是证明备份工具能用,而是证明“出了问题,你能把用户最关心的数据找回来”。
3.3 备份监控与告警:失败比不备份更危险
备份失败不可怕,可怕的是备份连续失败一周没人发现。备份监控不能只看“备份任务有没有执行”,要看“备份文件有没有生成、大小是否正常、校验和是否一致、是否成功传到异地”。四层都过了才算一次有效备份。
监控维度可以参考这几个:备份任务退出码是否为 0;备份文件体积与昨日对比是否低于阈值;异地副本是否存在且大小一致;备份日志里有没有ERROR、WARN关键字。告警渠道走值班电话,因为半夜备份失败大概率不会有人看即时通讯软件。
# 检查异地副本是否在 5 分钟内更新 find /remote_backup/ -name "*.xb" -mmin -300 >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "remote backup file missing" # 这里触发电话告警 fi备份文件大小异常也值得单独说。文件比昨天小了一半,往往不是数据量下降了,而是备份任务中途断掉但退出码仍然返回 0。脚本里只判断退出码是不够的,要把文件大小纳入告警基线。
4. 变更与高可用切换:审批流之外的三个硬约束
4.1 变更窗口:为什么金融库不敢“随到随改”
应用系统半夜发版本,顺手改一个数据库字段,看起来是小事,背后牵动的是整个变更管理体系。金融库的变更规范里一定会有一条:生产库不允许随到随改,所有 DDL 和危险 DML 必须进入变更窗口。
变更窗口的设定不是拍脑袋。核心交易库白天交易量大,DDL 加索引可能造成锁等待,进而拖垮整个业务;夜间系统跑批,同样不能动,批处理对数据一致性要求极高。我一般建议把变更窗口设在交易低峰且不是跑批时间段的固定时段,比如每两周一次,周三凌晨 1 点到 3 点,提前布告,让所有关联系统都知道“这个时间段数据库可能抖动”。
窗口期内还有两个硬性约束:第一,变更前必须做性能基线记录,包括主库的 QPS、连接数、慢查询数量,变更后做对比,用数据判断有没有引入风险;第二,窗口结束前必须留出至少十五分钟的观察期,不能改完立刻走人,要在这个时段内持续观察告警,确认没有异常才允许关闭窗口。
4.2 回滚不是备份:把回滚方案写进变更单
“这个脚本我测过了,不会出问题”是变更事故里出现频率最高的一句话。数据库变更最容易翻车的一点,是把“备份”和“回滚”混为一谈:备份了全库就觉得自己有后悔药,事实上全备恢复要几小时,业务早被投诉淹没了。
规范的变更单里,回滚方案必须具体到这一步:如果是加索引,回滚是DROP INDEX,执行时间预计多少秒;如果是改字段类型,回滚是改回原类型,但要考虑数据是否已被新代码写入;如果是删数据,回滚脚本必须提前写好INSERT ... SELECT,且被删的数据先从生产库导出成文件。回滚方案不能是“从备份恢复”,必须是能在五分钟内执行的逆向操作。
回滚脚本也要在测试环境预跑一遍。我见过太多人把回滚脚本写在变更单里,但从没执行过,等真正要回滚时才发现语法错误、表名写错、或者连账号权限都不够。回滚脚本和变更脚本一样,都是必须被测试的代码。
4.3 高可用切换演练:主备切换的检查清单
数据库同步工具和高可用组件把主备切换变得“看起来很简单”,实际上切换失败的案例比想象中多得多。金融规范里会要求至少每季度做一次真实的主备切换演练,这个演练的目的不是证明高可用软件能用,而是验证“整个链路”都能在切换后正常工作。
切换检查清单通常包括这些项:故障前主备数据延迟在阈值以内;备库有完整的账号、权限、插件;应用连接串指向的是 VIP 或域名,不绑定物理 IP;切换后read_only状态正确;binlog 和归档日志的同步方向没有反向;监控告警能自动识别到角色变化。其中应用连接串这一项最坑,很多高可用切换的失败不在数据库本身,而是应用的连接池还握着旧 IP,VIP 漂移了但应用不知道。
我在切换演练中习惯先做“只读切换”,也就是把备库提升为只读实例,验证查询流量可以切过去,再做完整读写切换。分两步走,每步验证通过再继续,避免一次切换失败后连原地返回都找不到入口。演练结束后的复盘也要留档,把“实际切换耗时”“意外项”“未验证项”写成清单,下次演练前逐条关闭。
5. 规范执行避坑:五条血泪经验
5.1 权限开了二十年没人清
现象:审计梳理时发现一个十年未登录的账号仍拥有生产库全部表的权限,而且它的密码还是初始密码,从未改过。
原因:账号回收流程缺失,开发人员离职或转岗后,DBA 不知道,账号自然没人管。权限只开不回收,权限范围只扩不缩,时间越久越难清。
解决:把账号清理变成季度例行任务。先拉出所有账号的最后登录时间,超过 90 天未登录的开发账号先禁用,再发通知确认,两周后无人认领直接删除。权限过期时间在发账号时就写清楚,到期自动停用。
5.2 备份脚本显示成功但备份文件却不可用
现象:备份任务每天 0 点准时执行,日志一切正常,文件大小看着也稳定。等真正要恢复时,xtrabackup --prepare报错,备份文件根本用不了。
原因:备份脚本里用的xtrabackup --backup没有加--prepare就结束了,或者说备份过程中 MySQL 实例发生过重启,备份文件处于不一致状态,但脚本没有校验这一点。
解决:备份脚本里必须包含完整的prepare步骤,并把prepare的结果作为备份成功的判定条件。不要只在备份机上做prepare,要在一个独立的恢复机或测试实例上做,确认能恢复才算数。
5.3 变更审批卡在流程里,深夜上线冒险提速
现象:变更单提交后迟迟没有审批,到了变更窗口时间,审批还挂着。操作人为了赶上窗口,绕过流程先把变更执行了,事后补单。
原因:流程设计出了问题,审批链路过长,审批人不在值班表里,深夜找不到人签批。操作人怕错过窗口要再等两周,就赌了一把。
解决:审批流程要设置动态审批人,变更窗口期间必须有值班审批人在线。同时把“窗口期无法完成审批”当成一种正常情况,准备预案:不是跳过审批,而是弃用本次窗口,等到下一个窗口期先审批后执行。
5.4 巡检只看告警面板,忽略慢查询和锁等待
现象:告警面板一片绿,但业务方隔三差五反馈“应用响应慢”。DBA 查了监控,CPU、内存、磁盘都在合理范围,没发现异常。
原因:监控面板只覆盖了基础设施和数据库可用性指标,没有覆盖 SQL 层面的性能问题。慢查询日志没开或开了没人看,锁等待和事务长执行时间被完全忽略。
解决:巡检脚本在采集基础指标的同时,必须查询慢查询日志表、information_schema.innodb_trx和锁等待状态,把运行超过阈值的 SQL 抓到明细。巡检的目的不是保证“库是活的”,而是保证“库的响应是健康的”。
5.5 应急切换后业务连不上,应用账号白名单没同步
现象:主库故障触发高可用切换,数据库实例在备库上正常启动,VIP 也漂移了,但业务连接全部失败。
原因:备库是克隆出来的实例,备库上的mysql.user表和账号白名单没有同步主库的变更。主库近期新加的账号、改过的密码、调整过的权限,都没有同步到备库。
解决:账号和权限的变更,执行后立即同步到所有从库和备库。在切换演练里增加“切完后用业务账号真实连接一次”的验证步骤,确认新账号能登录、密码正确、权限匹配,而不只是验证 VIP 能 ping 通。
6. 把规范变成巡检脚本:从人工到自动的最后一公里
6.1 巡检脚本骨架:用标准 Linux 命令和 SQL 组合成每日任务
规范最终要落地,靠的不是文档,是一套每天自动跑的巡检脚本。先看骨架,再看每一段的意图:
#!/bin/bash # 每日数据库巡检:采集健康指标并输出分段报告 DATE=$(date +%F) OUT=/var/log/db_daily_${DATE}.log { echo "===== $DATE 基础健康 =====" mysql -h127.0.0.1 -uroot -e " SHOW GLOBAL STATUS LIKE 'Threads_connected'; SHOW GLOBAL STATUS LIKE 'Threads_running'; SHOW GLOBAL VARIABLES LIKE 'max_connections'; " echo "===== 慢查询与长事务 =====" mysql -h127.0.0.1 -uroot -e " SELECT * FROM mysql.slow_log WHERE start_time > NOW() - INTERVAL 1 DAY ORDER BY query_time DESC LIMIT 10; SELECT trx_id, trx_state, trx_started, TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS trx_age_seconds FROM information_schema.innodb_trx WHERE trx_state <> 'COMMITTED' ORDER BY trx_started ASC; " echo "===== 备份与复制状态 =====" mysql -h127.0.0.1 -uroot -e "SHOW SLAVE STATUS\G" | grep -E "Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_Master" ls -lh /backup/ | tail -5 echo "===== 磁盘与系统负载 =====" df -h /data | tail -1 uptime } >> "$OUT" # 检测异常阈值,存在则触发告警 grep -E "Threads_running .*[5-9][0-9]|Seconds_Behind_Master: [1-9][0-9][0-9]" "$OUT" \ && echo "DB ABNORMAL" | tee -a "$OUT"这段脚本里的三个查询模块分别对应三件事:连接数基线反映“库是否还扛得住”,慢查询和长事务反映“业务响应为什么慢”,复制状态和备份文件反映“数据安全是否在线”。每个模块采到的数据不是给人肉看的,要落到固定路径的日志文件里,让趋势对比变成可能。
参数上注意阈值要按环境调:Threads_running在低峰期超过 30 就要排查,高峰期超过 100 可能才需要介入,不能套一个死值。慢查询的时间阈值也是一样,先按 2 秒筛一轮,再根据业务基线调到更严格的 500 毫秒,标准是只要能抓到 TOP 10 的异常 SQL,而不是把正常 SQL 都捞进来看。
6.2 把巡检结果接入现有运维体系
巡检脚本独自跑没有太大意义,要把它接入已有的大内存运维软件或监控平台,让它和告警事件、变更记录、值班日志联动起来。比较省事的做法是:脚本产出的日志直接丢给日志采集器,平台里配好关键字告警;脚本里最后一段检测到异常时,调用已有的告警接口触发电话通知。
这里有个容易踩的坑:巡检脚本运行本身不能影响生产库。查询information_schema.innodb_trx和mysql.slow_log时,要确保脚本的数据库连接走的是一个只读账号,且不对生产库做任何写操作。很多 DBA 图省事,用 root 跑巡检,结果巡检本身因为权限和连接方式问题干扰了线上业务,这就本末倒置了。
巡检脚本跑出来的数据要形成周报和月报。从经验来看,运维复盘最缺的不是零散告警,而是趋势:慢查询数量是不是在上升,连接数是不是每周都在逼近上限,备份文件大小是不是出现异常波动。这些趋势只有靠自动化采集才能留下完整的序列数据。
6.3 先在自己环境跑一周,再上生产
这套巡检脚本上线前,我自己一定会在测试环境先跑满一周,每天人工对比脚本输出和实际查询结果,确认没有误报也没有漏报,再去生产部署。第一次上生产也建议只采集不告警,观察三天,调整阈值后再打开告警开关。这一步虽然慢,但能避免“告警天天响,值班人被骚扰到免疫”的尴尬局面。
做金融数据库规范运维这么长时间,我最大的感受是:文档只是起点,能不能让团队在凌晨两点按文本能操作、能抉择、敢切主备、敢回滚,才是规范真正生效的标志。回滚脚本没测过的变更,比不做的变更更危险;数据恢复不了的全备,比不备份更容易误导人。希望这些踩过的坑、调过的参数、改过的脚本,能帮你在落地规范时少走几条弯路。
本文还有配套的精品资源,点击获取