实现基于 GitLab 的数据库 CI/CD 最佳实践
数据库变更一直是整个应用发布过程中效率最低、流程最复杂、风险最高的环节,也是 DevOps 流程中最难以攻克的阵地。那我们是否能在具体的 CI/CD 流程中,像处理代码那样处理数据库变更呢?

DORA 调研报告
DORA(DevOps Research & Assessment)是一家专注于 DevOps 的研究机构, 在该领域以专业与客观著称。自 2014 年以来,DevOps 调研了全球范围内超过 32,000 名专业人员,并以年度报告的形式对外发布研究成果。DORA 明确指出,将数据库变更纳入应用发布流程将显著提升整体发布效率。

这一结论并不令人意外。问题是,该怎么做?
一个完整的基于 GitLab 的数据库 CI/CD 工作流

通过 Bytebase,我们将实现一个完整的基于 GitLab 的数据库 CI/CD 工作流:
- 开发者将变更 SQL 脚本提交到代码分支;
- 触发 Bytebase 提供的 SQL 审核 CI 进行自动化 SQL 审核,并给出修改建议;
- 修改完成后的 SQL 脚本合并入主分支;
- 自动触发发布流程,脚本将被推送到 Bytebase 工具中;
- Bytebase 内置的自动审核将对变更语句进行二次确认,根据变更风险等级自动匹配审批流,根据审批流审批;
- 审批后的语句可以通过手动或自动触发在目标库中执行;
- 变更完成后的数据库最新 schema 结构将被自动回写入代码仓库;
- 确认变更完成后,触发下一阶段的应用发布流程。
通过 Bytebase 社区版实现
让我们一步一步看看这个过程怎样实现的。
第一步 通过 Docker 启动 Bytebase,并配置外部 URL
ngrok 是一个反向代理工具,我们需要它的公网地址,以便从 GitHub 接收 webhooks。这里使用 ngrok 是出于测试目的;生产环境建议使用 Caddy。

- 登录 ngrok Dashboard,并按照 Getting Started 步骤进行安装和配置。
- 在 Docker 中运行 Bytebase: ``` docker run --init \
--name bytebase
--restart always
--publish 5678:8080
--health-cmd "curl --fail http://localhost:5678/healthz || exit 1"
--health-interval 5m
--health-timeout 60s
--volume ~/.bytebase/data:/var/opt/bytebase
bytebase/bytebase:2.8.0
--data /var/opt/bytebase
--port 8080
3. Bytebase 通过 Docker 成功启动,你可以通过 `localhost:5678` 来访问。注册一个管理员账号。
4. 在命令行运行 ngrok http 5678 ,并获得公共 URL。

5. 登录 Bytebase,点击右上角的齿轮,将公共 URL 填入到网络部分的外部 URL,点击更新。### 第二步 在 Bytebase 种添加 GitLab.com 作为 Git Provider
1. 通过公共 URL 来访问 Bytebase,点击右上角的齿轮 > 集成 > GitOps,选择 gitlab.com,点击下一步。你会进入到第二步,拷贝 Redirect URI。

2. 访问 [GitLab](gitlab.com),点击头像,选择下拉菜单中的偏好设置,在左侧栏中选择应用。填写表格如下并保存:- Name: Bytebase- Redirect URI: 从 Bytebase GitOps 配置里步骤 2 里复制- Confidential: Yes- Scope: api

3. 从 GitLab 的应用页面复制 Application ID 和 Secret,然后粘贴到 Bytebase 的 GitOps 配置页面步骤 2 里。
### 第三步 在 Bytebase 中配置一个 GitOps 工作流
1. 访问 [GitLab](gitlab.com),并建立一个新项目 bytebase-gitlabcom-demo。将 Visibility Level(可见级别)设置为公共。点击建立项目。
2. 访问 Bytebase,进入项目 Sample Project。点击 GitOps 标签,选择 GitOps 工作流。点击 配置 GitOps。
3. 选择 GitLab.com(就是你在上一步配置的),然后选择 bytebase-gitlabcom-demo 这个项目。你会来到步骤三,保持其它参数不变,滑动到页面底部,勾选 基于 GitLab CI 开启 SQL 审核。点击完成。
Image
4. 系统会自动在 GitLab 中建立实现 CI 的 MR,跳转到 GitLab 中手动合并。

5. 回到 Bytebase,你会见到 GitOps 工作流已设置成功。### 第四步 建立一个 MR(合并请求)去触发 SQL 审核 CI
1. 点击界面顶端环境,你可以看到在 Prod 最下方有连接了一个 SQL 审核策略,点击编辑,你会看到有 3 条开启的规则。它们将通过 CI 应用。

2. 为了测试 SQL 审核 CI,我们将创建一个合并请求来更改 Prod 数据库 schema。不过,我们会让它先违反下 SQL 审核策略。转到 GitLab 上的 bytebase-gitlabcom-demo。单击新建分支,命名为 add-nickname-table-employee,点击创建分支。
3. 在新分支上创建子目录 bytebase,并创建子子目录 prod。在 prod 目录中创建文件 `employee##202309262500##ddl##add_nickname_table_employee.sql`。将以下 SQL 脚本复制到文件中,并提交更改。
ALTER TABLE "public"."employee" ADD COLUMN "nick_name" text;
4. 创建包含上述提交的合并请求。SQL 审核 CI 将自动运行并显示失败消息。不过,无论 CI 结果如何,你仍然可以合并它。

5. 更新 SQL 脚本并提交到当前分支。SQL 审核 CI 将再次运行并显示通过信息。单击合并。
ALTER TABLE "public"."employee" ADD COLUMN "nick_name" text NOT NULL DEFAULT '';

6. 返回 Bytebase 中的 Sample Project,你会看到推送事件产生了一个工单。

7. 点击 issue/102 到问题详情页面。因为没有配置审批流或手动发布,此工单会自动发布。您可以点击查看变更来查看差异。
## 通过 Bytebase 企业版解锁更多功能
您可以升级到企业版,解锁更多功能。点击左下角的开始免费试用并升级到企业版,点击顶部实例,为现有的两个实例分配证书。### 手动发布
在环境 > 2.Prod,找到发布策略,然后选择 人工发布 > 需要 DBA 或者 Bytebase 实例所有者发布。
### 自定义审批
1. 访问设置 > 安全性 & 策略 > 自定义审批。将项目 Project Owner -> DBA 设置为 DDL > 高风险的审批流。

2. 访问设置 > 安全性 & 策略 > 风险中心。点击添加规则,然后点击加载第一个模板,点击添加。
### 最新 schema 写回
Schema 变更完成后,Bytebase 会将最新 schema 写回 Git 代码库。这样,团队在 Git 中就始终有一个数据库 schema 的标准真实源。
1. 返回 GitLab,新建一个分支 `add-country-table-employee`。在 bytebase/prod 目录下创建文件 `employee##202309261700##ddl##add_country_table_employee.sql`。将以下 SQL 脚本复制到文件中并提交更改。
ALTER TABLE "public"."employee" ADD COLUMN "country" text NOT NULL DEFAULT '';
2. 返回 Bytebase,转到新创建的工单,它符合 Project Owner -> DBA 的审批流程。

3. 按照审批流程点击批准后,横幅将显示等待发布。然后,负责人就可以点击 发布了。
4. 回到 GitLab,在 `bytebase/prod/` 下有一个新的文件 `.employee##LATEST.sql`,包含了 Bytebase 写回的最新 schema。### Schema 漂移
Bytebase 内置了 schema 漂移检测功能,可以检测到意外的 schema 变更。让我们使用 SQL 编辑器管理员模式来模拟一下。
1. 点击右上角的终端图标(SQL 编辑器)。你将跳转到 SQL 编辑器。点击管理员模式。在此模式下所做的一切与直接连接服务器相同,Bytebase 不会记录。
2. 选择左侧的 (Prod) Employee,粘贴并运行以下脚本:
ALTER TABLE "public"."employee" ADD COLUMN "city" text NOT NULL DEFAULT '';
```
- 返回 Bytebase 主页,点击顶部的数据库, 选择 Prod 下的 employee。点击现在同步。看到成功消息后,刷新页面。你将看到 schema 漂移。你可以在实例详情页配置自动扫描,以避免手动同步。

- 访问异常中心,也会看到 schema 漂移。
总结
有了 Bytebase,你就有了一套完整的 GitLab 数据库 CI/CD 工作流程。您可以将此工作流程应用到自己的项目中,并根据自己的需要进行定制。 Bytebase 也支持 GitHub,Bitbucket 以及 Azure DevOps。具体的配置步骤可以查看文档。
💡 你可以访问官网,免费注册云账号,立即体验 Bytebase。
相关文章:
实现基于 GitLab 的数据库 CI/CD 最佳实践
数据库变更一直是整个应用发布过程中效率最低、流程最复杂、风险最高的环节,也是 DevOps 流程中最难以攻克的阵地。那我们是否能在具体的 CI/CD 流程中,像处理代码那样处理数据库变更呢? DORA 调研报告 DORA(DevOps Research &am…...
android关闭键盘方法
Android开发中经常会遇到隐藏键盘的需求,例如登录界面,输入账号密码后需要点击界面其它部位,隐藏键盘。为此,分享前几年自己使用的方法,最近亲自测试,仍然有效。 方法一、Window window getWindow(); Win…...
ACK 云原生 AI 套件:云原生 AI 工程化落地最优路径
作者:胡玉瑜(稚柳) 前言 在过去几年中,人工智能技术取得了突飞猛进的发展,涵盖了机器学习、深度学习和神经网络等关键技术的重大突破,这使得人工智能在各个领域都得到广泛应用,对各行各业产生了深远的影响。 特别值…...
工程企业管理软件源码-综合型项目管理软件
工程项目管理软件(工程项目管理系统)对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营,全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&am…...
stm32mp157中断简单应用
设置按键中断,按键1按下,LED亮,再按一次,灭 按键2按下,蜂鸣器响。再按一次,不响 按键3按下,风扇转,再按一次,风扇停 main.c #include "gpio.h" #include &…...
智慧机场数字孪生大屏升级智慧出行全方位服务
在宁波栎社国际机场的信息中心大楼内,一块大屏幕上展示了一座“数字孪生”机场。通过点击屏幕上的各个板块,可以实时查看现场情况,一旦出现突发状况,还可以立即启动闭环处置流程…… (图源自宁波机场) 在数…...
微信小程序 js中写一个px单位转rpx单位的函数
大家写东西自然还是会比较喜欢用rpx 但是 事实证明 在js中 还是px好用 因为很多单位交互的函数还是只返回px单位的 理论上将 750 rpx 是整个屏幕的宽度 那么 我们可以这样写一个函数 pxToRpx(px) {//获取整个屏幕的宽度单位 pxlet screenWidth wx.getSystemInfoSync().scree…...
第14章总结:lambda表达式与处理
14.1: lambada表达式 14.1.1:lambada表达式简介 无参数 package fourteen; interface SayhHi{ String say();//抽象方法接口 } public class NoParamDemo { public static void main(String[] args) { //无参数 …...
多尺度retinex图像去雾算法matlab仿真
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 clc; clear; close all; warning off; addpath(genpath(pwd)); rng(default)img_in im2doub…...
蓝桥等考Python组别十八级005
第一部分:选择题 1、Python L18 (15分) 运行下面程序,输入30,输出的结果是( )。 t = int(input()) if t < 30: print(0) else: print(t // 15 * 2) 4102030正确答案:A 2、Python L18 (15分)...
redis在linux系统的安装与使用
一、单机安装Redis。 1.安装redis依赖 在控制台输入 yum install -y gcc tcl2.上传安装包 下载好的安装包上传到/usr/local/src/ 上传方法: 1.确保你拥有Linux服务器的IP地址、用户名和密码。 2.在Windows上,打开命令提示符(Command Promp…...
PanoFlow:学习360°用于周围时间理解的光流
1.摘要: 光流估计是自动驾驶和机器人系统中的一项基本任务,它能够在时间上解释交通场景。自动驾驶汽车显然受益于360提供的超宽视野(FoV)◦ 全景传感器。 然而,由于全景相机独特的成像过程,为针孔图像设计…...
C# - 常用API
Assembly.GetCallingAssembly 方法 获取当前方法的调用程序集: Console.WriteLine("FirstMethod called from: " Assembly.GetCallingAssembly().FullName); Assembly.GetExecutingAssembly 方法 获取包含当前执行的代码的程序集: //获取当前执行的代码的程序集…...
新式茶饮品牌如何写出生活感软文
居民消费水平的提升使新式茶饮品牌的市场不断扩张,在竞争激烈的茶饮市场中,品牌提高知名度的主要方式之一就是软文营销,而生活感软文是茶饮软文中较为常见的类型,它能有效拉进品牌与消费者之间的距离,那么新式茶饮品牌…...
使用c++视觉处理----canny 边缘检测、sobel边缘检测、scharr 滤波边缘检测
使用c视觉处理canny 边缘检测、sobel边缘检测、scharr 滤波边缘检测 #include <opencv2/opencv.hpp>int main() {// 读取图像cv::Mat image cv::imread("1.jpg", cv::IMREAD_GRAYSCALE); // 转为灰度图像if (image.empty()) {std::cerr << "无法加…...
gogs和drone如何配合使用
上篇介绍了drone和gogs安装方法,这次介绍这两个如何使用,此篇文章主要介绍在物理机上进行发布。 此处用到的java项目地址:https://gitee.com/huningfei/demo-test 一 配置gogs 1.1 在Gogs中配置指定仓库的”.drone.yml“文件 1.2 ssh-drone…...
Feign客户端的配置与使用
feign Feign的基本使用Feign客户端抽取 Feign的基本使用 Feign是一个声明式的Web服务客户端,它使得编写Web服务客户端变得更加简单。 1、首先,需要在项目中引入Feign的相关依赖。在Maven项目中,可以添加以下依赖: <dependen…...
【数据结构】队列(Queue)实现详解
🚩纸上得来终觉浅, 绝知此事要躬行。 🌟主页:June-Frost 🚀专栏:数据结构 🔥该文章主要了解实现队列的相关操作。 目录: 🌍 队列🔭概念🔭结构&…...
23.10.13数据库升级流程记录
23.10.13数据库升级流程记录 hello,我是阿昌,今天记录一下数据库升级的流程,内容如下: 一、升级的内容 将之前的数据库升级为8.0版本,切只涉及一个分库; 二、升级的时机 涉及到数据库升级,…...
【three.js】结合vue进行开发第一个3d页面
一、创建vue项目 新建一个项目目录,在集成终端打开,输入 npm init vitelatest 回车后,依次输入项目名,选择vue和js开发 然后安装依赖并运行项目 二、安装three 接下来我们开始安装three npm install three 三、Three.js 的…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
