游戏数据库版本更新神器Flyway

网易游戏基础架构平台

游戏热爱者

Ychun
网易游戏高级运维工程师,负责多个游戏产品的运维工作;关注自动化、容器、业务全链路监控等领域

背景介绍

本文开始之前,总结一下传统数据库更新比较经典的对话,如下:

Q:小杨同学,DB更新脚本执行失败,麻烦看看
A:查看日志后,sql文件没有use db语句Q:小杨同学,DB更新脚本已经执行完毕,怎么数据没有更新呢?
A:没修改version.txt文件,qa更新还是按照旧的sql文件进行更新Q:小杨同学,QA刚把sql文件执行顺序弄错了,可能需要恢复数据重新更新
A:需要从备份恢复数据Q:小杨同学,QA刚重复更新了一个sql文件,不知道有没有问题
A:需要花一些时间去review sql脚本,定位重复更新是否有问题Q:小杨同学,麻烦更新下苹果/安卓审核服的DB,几个月没更新需要补好几个版本
A:得查下外服最近的更新记录,慢慢补上……

数据库更新,一直是运维人员重点关注的工作之一,因此数据库更新的目标要达到:避免重复更新,漏更新,更新顺序错乱;能够记录更新历史,确保更新有迹可查;sql 符合一定的规范,以便于自动执行和处理。

传统数据库更新现状:维护一个 version.txt(记录更新目录 /sql 文件更新顺序) 文件,sre 编写数据库更新脚本,每次都要设定一个比较复杂的更新流程:和程序约定好 sql 文件命名规范 -> 程序上传 sql 文件 -> 特定服务器下载文件到指定目录 -> 数据库备份 -> 更新脚本执行数据库更新 -> 有问题排查或用备份恢复,而且还有各种意料之外的事情发生,在有限的维护时间内处理其实是有相当大难度。

传统数据库更新痛点:

1)程序忘记修改 version.txt 文件;

2)程序 sql 文件忘记添加 use db 语句;

3)程序误删相关目录或者文件;

4)qa 没有按照顺序更新或者重复更新;

5)sre 需要花很多时间分析 sql 内容定位问题并恢复数据;

开源数据库管理工具 Flyway 可以轻松完成数据库版本更新功能,解决传统数据库更新的痛点,而且能够做到:

1)不会重复更新;

2)更新顺序不会发生错乱;

3)能够记录更新历史;

4)数据库更新版本能够和程序版本一一对应;

Flyway 工作原理

Flyway 的每个更新叫做一个 migration,在执行 migration 的时候会指定更新哪个数据库,然后去对应的目录寻找 sql 文件来进行更新。Flyway 会自动在数据库中新建一个名为 "flyway_schema_history" 的表(备注:Flyway V5.0 之前的版本,表名叫做 schema_version),该表会记录当前已更新的 sql 信息,下次会接着按照 sql 版本的顺序往下更新,如下所示:

flyway_schema_history:

上图 table 中的部分重点列的数据的含义:

  • version:不同的版本号
  • description:本次版本更新的描述,按照 sql 文件命名规范,从 sql 文件名中提取的内容
  • script:执行的脚本名
  • installed_by:执行脚本的数据库用户名
  • installed_on:开始执行 sql 的时间
  • execution_time:脚本执行时间 (毫秒 )
  • success:执行结果,1 表示执行成功

flyway 根据 flyway_schema_history 表中的信息记录,在每次执行 migtation 的时候,只执行之前没有执行过的 sql,并且按照 Vsersion 的顺序执行;要使 flyway 能够获取到上图 table 中的相关信息,sql 目录结构和 sql 文件命名必须满足其规范 ;

1)目录结构

-/flyway/sql/
|-- database_01/                   #  以数据库名命名的目录
|   |-- V1__initial.sql            #  按照 sql 命名规则命名的 sql 文件,下同
|   |-- V2__first_changes.sql
|   |-- V3__add_tables.sql
|   |-- V4__init_data.sql
|-- database_02/                   #  以数据库名命名的目录
|   |-- V1__initial.sql            #  按照 sql 命名规则命名的 sql 文件,下同
|   |-- V2__modify_columns.sql
|   |-- V3__add_user_tables.sql
|   |-- V4__init_data_for_user.sql
...                                #  可以有多个数据库,按照上面的范例定义即可

2)sql 文件命名规范sql 文件名必须严格按照本规则命名,否则将会无法更新!

格式:
V[Version]__[Description].sql#  以大写的 V 开头,小写的 .sql 结尾;
# Version:数字和小数点组成的版本号,由用户自行定义,不能有字母!!!按大小顺序递增。例如:1/2/3/3.1/3.2/3.2.1/3.2.2 等
# Description:对本 sql 文件的描述信息。
# Version 和 Description 之间用两个下划线 "__" 隔开。
#  样例:V1__initial.sqlV2.1__first_changes.sqlV3.1.1__add_tables.sql

Flyway 支持的关系型数据库

项目实战

本文主要介绍的是 mysql 数据库使用 flyway 的实战经验;

程序操作指引

操作指引

1)将DB的sql文件与服务端版本文件一起提交,并严格遵守上述的目录结构和sql文件名规范要求;
2)sql文件内容中不需要用use语句指定数据库;
3)sql文件内容采用增量修改的方式提交,尽量不要有drop table再create table的语句,避免误删数据(除了非常确定该表中的数据无用!);
4)如果提交到svn中的sql文件已经被更新到了任一个游戏服,此sql文件不可再修改或删除;
5)sql文件内容,事务数量越小越好,避免sql执行部分失败后,需要回滚相关操作;

注意事项

#重要的事情说三遍
一般情况下:
只增量添加sql文件,不要删除和修改!
只增量添加sql文件,不要删除和修改!!
只增量添加sql文件,不要删除和修改!!!只有一种例外情况可以删除或修改一个已经提交到svn的sql文件:该sql文件提交到svn之后尚未更新到任何游戏服,因为按照Flyway的更新逻辑,DB更新是以sql文件为粒度的,在DB更新之前的sql内容修改是没有关系的;但是如果一个sql文件已经更新到某个服务器,再去修改它,那么再次修改的内容将不会在该服务器上被执行。

SRE 操作指引

Flyway 安装部署

官方文档:https://flywaydb.org/documentation/commandline/#download-and-installation

version=5.2.4  #  可以在 Flyway 官网查看最新的版本号,此处以当前(2019.06.06)的最新版本为例。
cd /home/xxxx
wget -qO- https://repo1.maven.org/maven2/org/flywaydb/flyway-commandline/${version}/flyway-commandline-${version}-linux-x64.tar.gz | tar xvz
sudo ln -s `pwd`/flyway-${version}/flyway /usr/local/bin

Flyway 的默认配置文件:

vim flyway-${version}/conf/flyway.conf
flyway.url=jdbc:mysql://host:port/dbname?useSSL=false
flyway.user=xxxxx
flyway.password=xxxxxxxxx

Flyway 执行可以使用以下两种方式:
1)直接在 flyway 命令行中直接加上参数,无需配置文件;2)在配置文件中指定好默认的配置,无需参数;

Flyway 更新 DB 指令 方法一:指定 schemas 来更新。Flyway 从默认目录(flyway-version/sql/{database})来读取 sql 文件

#  同步 sql 版本文件到 Flyway 默认 sql 目录
rsync -azL --delete ${updating_dir}/ /home/${project_user}/flyway/sql/${database}/#  执行 migrate 指令
flyway -baselineOnMigrate=true -baselineVersion=0 -schemas="${database}" -user="${user}" -password="${password}" -url="jdbc:mysql://${host}" migrate

方法二:直接指定 sql 目录来更新。直接指定 locations 参数【推荐】

#  在参数中指定 sql 文件的位置,直接执行 migrate 指令
flyway -baselineOnMigrate=true -baselineVersion=0 -user="${user}" -password="${password}" -url="jdbc:mysql://${host}" -schemas=${database} -locations=filesystem:/home/xxx/server/database/htdocs_local/db/alter/stg/ migrate

备注:两者并无本质差异,推荐使用方法二直接参数中指定 locations 的方式,少了一步 rsync,减少出错概率。

参数说明:

1、-baselineOnMigrate=true :表示如果当前DB未使用Flyway的话,以当前DB版本为基线版本
2、-baselineVersion=0:指定基线的版本,第一次使用 flyway 的时候指定为0,之后可以指定为当前版本,当前版本参考 flyway_schema_history 中的记录。
3、-schemas:数据库名
4、-locations:sql文件目录
5、migrate:对DB进行migrate更新
6、-user -password -url:用户名、密码和数据库访问地址信息

更新流程

1、程序按照Flyway规范提交新版本的sql文件;
2、提交阿拉丁流程来更新DB;
3、DB Client机器上备份数据库;
4、DB Client机器上下载新版本的sql文件;
5、执行Flyway进行DB更新;
6、如有报错,则进行排查并修复后重新更新;

问题排查

sql 文件的 checksum 不一致

原因:sql 文件被更新之后,文件内容进行了变更,再次执行更新会有这个报错 ; 解决方法:执行 flyway repair;

flyway -baselineOnMigrate=true -baselineVersion=0 -user="${user}" -password="${password}" -url="jdbc:mysql://${host}" -schemas=${database} repair

sql 文件描述不一致

原因:sql 文件被更新之后,文件名有变更 ; 解决方法:修改 flyway_schema_history 表中该 sql 文件对应的 description 字段 ;

Migration V6.7__xxx_xxx.sql failed

原因:sql 文件内容执行失败 ; 解决方法:根据 Flyway 输出的 Error Message 进行对应处理即可 ;

#注意:
1)如果对这个sql回滚,然后修改后重新提交的话,需要删除flyway_schema_history表中的该行记录;
2)如果修改内容后重新执行的话,需要执行repair指令修复下checksum;
3)如果手动执行完毕该sql内容的话,需要在对应的flyway_schema_history表中将该行的success字段改为true;

Validate failed: Detected failed migration to version 6.7

原因:该 sql 文件之前已经更新过,但是执行失败了 ; 解决方法:灵活处理 flyway_schema_history 表 ;

#注意:
1)如果对这个sql回滚,然后修改后重新提交的话,需要删除flyway_schema_history表中的该行记录;
2)如果手动执行完毕该sql内容的话,需要在对应的flyway_schema_history表中将该行的success字段改为true;

Validate failed: Detected resolved migration not applied to database: 2.7

原因:该版本的 sql 之前已经通过 Flyway migrate 更新过,但是新版本中该文件被删除了,导致验证不通过; 解决方法:flyway_schema_history 将该记录删除,或者在 flyway 命令中加上跳过这个验证的参数:-ignoreMissingMigrations=true;

WARNING: DB: Duplicate index 'idx_flyway_a_index' defined on the table 'sbtest.sbtest1'. This is deprecated and will be disallowed in a future release. (SQL State: HY000 - Error Code: 1831)

原因:理由不明,索引是正确添加的,但是会有 WARNING; 解决方法:不用处理 , 可以忽略;

总结

规范化管理业务变更一直是 sre 工作目标,数据库做为业务的核心,业务 sre 理应管控全局,对其进行规范化的管理,避免各种误操作带来的问题或故障。多个项目数据库更新使用 flyway 后,传统数据库更新带来的痛点不会再变为 sre 的负担,而且能够高质高效的完成每一次变更。

往期精彩

谨防!Post 打爆 /tmp 分区

DevOps之Gitlab-CICD实践篇

iOS 消息推送那些事儿

Dockerfile最佳实践

ceph部分数据所有副本先后故障的抢救

游戏数据库版本更新神器Flyway相关推荐

  1. flyway版本号_数据库版本管理工具-flyway

    flyway产生背景 在日常开发中,经常遇到数据库变更,字段增减调整,需要维护多个不同数据库时是十分痛苦的事情.代码可以使用svn,git等工具进行管理,那么数据库的版本可以使用Flyway 一款小工 ...

  2. 数据库版本管理工具Flyway应用

    2019独角兽企业重金招聘Python工程师标准>>> Flyway介绍 Flyway是一款开源的数据库版本管理工具,它更倾向于规约优于配置的方式.Flyway可以独立于应用实现管理 ...

  3. 数据库版本管理工具-flyway

    写在前面 在日常开发中,经常遇到数据库变更,字段增减调整,需要维护多个不同数据库时是十分痛苦的事情.代码可以使用svn,git等工具进行管理,那么数据库的版本可以使用Flyway 一款小工具,就可以大 ...

  4. sql脚本对比工具_Java开发中用到的数据库迁移工具(flyway)

    什么是数据库版本管理? 任何web软件和应用程序都需要强大的数据库管理工具,因此开发者选择一款合适的数据库管理工具尤为重要.本文列出了几款好用的数据库管理工具(有些并非开源或免费),以供开发者们参考选 ...

  5. MySQL数据库同步神器 - Gravity - 比Datax好用

    MySQL数据库同步神器 - Gravity 原始地址:https://github.com/moiot/gravity 同步地址:  https://gitee.com/yunwisdoms/gra ...

  6. 数据库版本管理工具 -- Flyway

    目录 一.Flyway简介 二.如何使用Flyway 三.核心概念 1.Migration 2.每个migration支持两种编写方式: (1)java (2)sql (3)所有的migration都 ...

  7. 游戏大版本更新和热更新

    游戏上线后,遇见bug或者需要更新内容(包括资源,玩法,数值调整,游戏脚本等)的时候,一般有2种做法.第一种,发个新包,然后让玩家下载新的版本:第二种,在游戏内更新,游戏启动时去下载需要更新的资源.第 ...

  8. unity热更- 2 游戏大版本更新和热更新

    游戏上线后,遇见bug或者需要更新内容(包括资源,玩法,数值调整,游戏脚本等)的时候,一般有2种做法.第一种,发个新包,然后让玩家下载新的版本:第二种,在游戏内更新,游戏启动时去下载需要更新的资源.第 ...

  9. 腾讯游戏数据库管理员Robin:仓管员团队的发展自白

    原标题:腾讯游戏数据库管理员Robin:仓管员团队的发展自白 文/崔玉明 支付宝.携程的连续故障,让大家认识到运维的重要性,而真正的运维不应和故障联系在一起.表面看是运维债务的问题,其实是运维人在背后 ...

最新文章

  1. PCL深度图像(2)
  2. 「GAN优化」如何学会以正确的姿势定量评价你的GAN
  3. mysql错误代码 集合
  4. 《R语言数据挖掘:实用项目解析》——第2章,第2.9节无参数方法
  5. Algs4-1.4.8计算输入文件中相等的整数对的数量
  6. 详细讲解JAVA中的IO流
  7. TypeScript入门-接口
  8. 关于mysql无法添加中文数据的问题以及解决方案
  9. javascript-阻止默认行为发生
  10. 医学科研中的作用_医学方复旦附属中山医院科研技能训练营开课啦!一起来感受数据挖掘的魅力!...
  11. Pytorch permute()的简单用法
  12. vpp之node节点分析一: dual类型节点
  13. mysql 数据库存放图片路径_mysql数据库可以存图片路径?
  14. 浅谈全国统一规范普通高等学校学费标准问题
  15. 远程办公与人心、机制、工具
  16. 强化学习中 on-policy与off-policy 的理解;如何区分on-policy 与 off-policy;RL更新策略、policy结构总结
  17. 最公正海贼王实力排行TOP50!
  18. 均方距离计算公式_均方末端距的统计计算法.ppt
  19. foxmai邮件服务器pop,全球邮企业邮箱Foxmail POP3/IMAP协议设置方法
  20. javascript编码调试环境-ide和调试工具

热门文章

  1. 自制力的本质是什么?怎样才能变得自律?
  2. 如何查mysql里有多少条数据_mysql快速查询数据库中有多少条数据
  3. 编写解析绝对定向程序matlab,相对定向和绝对定向解析过程(全面).ppt
  4. 计算机是如何跑起来的百度云,《程序是怎样跑起来的》(下)
  5. Spark大数据技术与应用期末总结大题
  6. Redis基于Set如何实现用户关注模型?
  7. 【题解】A1004 求三个数的平均数
  8. 笔记本固态硬盘和普通硬盘的区别
  9. pip使用豆瓣源进行安装下载
  10. 通过爬虫爬取四川省公共资源交易平台上最近的招标信息 --- URLConnection