1.案例解读|高盛 Goldman Sachs 如何做数据库变更
2.求大智慧或同花顺“假阴真阳”主图源码
案例解读|高盛 Goldman Sachs 如何做数据库变更
本文重点
近年,假阴源码高盛采用了标准的假阴源码 SDLC 来构建和部署应用程序。这包括管理新系统和现有系统的假阴源码数据库 schema ,这比管理应用程序代码更加困难。假阴源码在本文中,假阴源码我们将描述我们最近开源的假阴源码怎么自己创作源码数据库部署工具 Obevo 是如何帮助高盛的企业级应用程序的数据库纳入 SDLC 管控的。
企业的假阴源码数据库部署的问题
将数据库定义引入到标准的 SDLC 流程中是具有挑战性的,尤其是假阴源码考虑到数据库的状态以及执行增量迁移的需求。因此,假阴源码许多应用程序没有自动化或流畅的假阴源码数据库部署过程。我们的假阴源码目标是将数据库 schema 管理纳入与应用程序相同的 SDLC 中:通过将所有定义提交到版本控制系统 (VCS) 并通过标准的构建/发布机制部署。
这项工作由我们实际数据库系统使用案例的假阴源码多样性而变得复杂:
无论使用何种案例,由于大量分布各地的假阴源码开发人员都在进行变更,SDLC 本身都有复杂之处。假阴源码
虽然现有的假阴源码开源工具可以处理简单的案例,它们无法处理我们一些现有系统的规模和复杂度。但是我们不能放任这些现有系统没有适当的 SDLC:它们是正在开发和发布的关键系统。
因此,我们开发了 Obevo,一个能处理所有此类使用案例的工具。Obevo 的关键差异化因素在于能够 按文件维护数据库对象(类似于更常见的 按文件存储类定义),同时仍管理增量部署。
在本文中,我们将讨论数据库部署问题,dsdv源码详解然后演示基于对象的项目结构如何帮助我们优雅地管理各种对象和环境类型的上百上千个 schema 对象。
数据库对象类型(有状态 vs 无状态)
首先,我们来回顾一下不同数据库对象类型的部署语义,因为这会影响工具的设计。
有状态对象(例如:表) 需要增量修改其定义,而不是完全的定义替换。以下是添加两列到 MyTable 中的示例:
理想情况下,我们可以通过一个 SQL 语句来把数据库带到终态,该 SQL 定义了一个具有四列的表。不过 SQL 其实无法提供可行的解决方案:
相反,关系型数据库管理系统 (RDBMS) 允许用户使用 ALTER 语句来修改现有表。
某些列更新可能需要进行数据迁移,例如从一个表中移动列数据到另一个表中。
因此,每个对象都是应用多个脚本片段的结果;初始脚本片段创建对象,后续脚本片段修改对象。
无状态对象(例如:视图,存储过程) 可以通过指定其完整对象定义来创建和修改。
我们也将静态数据文件(代码或参考数据表)视为无状态对象。虽然它涉及到表数据,但是这些数据在你的脚本中已经完全定义,并且可以通过批量 delete + insert 或选择性 insert + update + delete 操作部署到表中。
数据库部署工具原则
Martin Fowler 的ssltls通讯源码 Evolutionary Database Design 对基于源头控制的数据库部署工具遵循的主要原则进行了精彩阐述,下面是其中一些具体相关的要点。
基于 UI 的管理可能适用于非技术用户,但我们建议开发团队将其数据库脚本片段存储在源代码控制中(和对待其它应用程序一样),并以自动化方式调用部署。
在我们看来,在企业环境中,例如在当前数据库表状态和代码完整视图之间自动计算迁移是有风险的。
数据库部署工具要求
我们根据以下需求评估数据库部署工具的处理能力:
A) 将增量更改部署到现有数据库中 这是数据库部署工具的主要功能;大多数生产环境都是通过此方式执行的。在一些非生产环境中,尤其是在发布到生产之前的 QA 环境中进行测试时,也会使用此方法。
B) 将完整 schema 部署到空白数据库中 开发人员可能希望将其部署到一个空白沙盒数据库以进行以下操作:
这可以通过以下几种方式来完成:
C) 易于维护和阅读 在我们进行数据库部署改进之前,我们看到一些团队为每个数据库对象维护一个文件,其中包含对象的定义,尽管这些文件并未用于部署。
这似乎没有意义,但我们获得了一些见解:
通用数据库部署工具设计主要部署算法
根据上述原则,大多数基于源代码控制的数据库部署工具(包括 Obevo)的工作方式如下:
有状态和无状态对象部署语义
对象类型对变更集计算语义会产生影响。
为了演示有状态用例,我们将 deploy 部署包 v1 以获取右侧表。
假设有人修改了 M3 并重命名了列,然后我们进行重新部署。我们期望会发生什么?
工具检测到不匹配:
因此,docker php源码一般规则是:有状态对象脚本一旦部署就不能修改。
某些选择性功能可以让我们在需要时绕过这个问题,例如:
数据库部署工具的实现选择
考虑到它们的底层算法相似,部署工具因几个实现要点而异。
1)如何将脚本片段组织成文件
有如下几种方式将脚本片段进行分组:
2)如何排序部署要部署的脚本片段
需要考虑:
接下来,我们将详细介绍 Obevo 是如何解决这两个问题的。
Obevo 设计:基于对象的脚本组织
我们主要的数据库部署问题是如何管理 schema 中大量对象的开发、维护和部署。同时,还有开发人员在编写应用程序时处理他们的数据库对象。
因此,我们希望提供一种对开发人员来说易于理解的体验,这导致了我们根据对象名称组织脚本。在本节中,我们将深入探讨这些详细信息。(该结构增加了一些排序方面的挑战,下一节详细介绍)
项目结构基础
我们根据适用于那些对象的脚本片段来组织,以下是一个示例。
文件结构根据对象是否具有状态而不同。
分析:无状态对象处理
基于对象的结构对于无状态对象方便很多,因为完整的无状态对象定义可以在文件中维护,并且可以就地修改。
作为比较,微软手机源码在增量有状态的方式中,技术上可以处理无状态对象部署,例如作为持久化多个版本的增量脚本。然而,这会导致数据库脚本存在冗余,因为对象在多个版本中发生变化。
分析:可读性
从维护的角度来看,这个项目结构有一些优势:
为了进行比较,可以拿一个项目结构的例子来说明,其中一个文件与迁移或发布相关联,因为许多工具都支持这种方式。这可能会导致一些问题:
从代码审查/发布审查角度来看:面向对象的结构意味着特定版本中所有更改都会分散在文件中。乍一看,似乎很难审核要部署到下一个版本的脚本片段。但是,我们仍然可以通过比较 VCS 历史记录和标签来审核发布的代码 - 就像处理应用程序代码一样。
分析:对于开发者的好处
使用 Obevo 项目结构,开发人员也好处多多。
由于对象的脚本片段放置在单个文件中,我们可以轻松地在测试中部署单个对象,这对于像在内存数据库中进行数据访问 API 的单元测试等情况非常有用。
开发人员也可以利用 ORM 工具从应用程序生成 DDL,并与迁移脚本进行协调。简洁起见,这里我们不深入讨论,但你可以在文档中了解更多。
Obevo 设计: 通过依赖性分析进行排序
虽然选择基于对象的项目组织方式提供了上一节中提到的许多好处,但它也使排序变得更加复杂。
对象可以互相依赖,随着我们把 schema 扩展到数百或数千个对象,手动指定顺序变得越来越困难。
让我们描述一下我们是如何克服这些挑战的。
排序算法
不是所有的脚本片段都互相依赖,因此我们在对象依赖声明的明显约束下是有一些灵活性的。
因此,我们使用一个简单的图算法来设计解决方案。
比如以下示例语句:
注意以下几点:
这适合使用有向图表示,其中图节点是脚本片段,边是顺序依赖关系。
我们现在可以使用拓扑排序算法得出一个可接受的顺序,以保持这些顺序约束并成功部署我们的数据库。
拓扑排序可以产生许多可接受的顺序,但是我们会调整算法使用方式以给出单一一致的顺序,以便在各个环境中具有一致性。
现在最后一个细节:如何在脚本片段中声明依赖关系?
依赖声明和发现
我们发现最简单的方法是在脚本中声明依赖项。请参见下面 TABLE_B.fkA 脚本片段中的dependencies 属性。
然而,对于大型数据库来说这并不友好(想象一下注释数百或数千个对象),因此我们需要一种自动检测依赖关系的方式,同时仍允许开发者覆盖。
我们使用两种策略来推断依赖关系:
有状态迁移的内部对象依赖关系:
我们允许有状态的对象定义多个脚本。很自然地,我们认为在同一个文件中编写的迁移按照它们编写的顺序进行部署,因此我们推断出这样的依赖关系(下图)。
通过文本搜索实现跨对象依赖关系
为检测跨对象的依赖关系,我们需要搜索脚本内容以查找相关对象。
从技术上讲,理想的方法是解析 SQL 以查找这些对象。然而,这非常困难,因为我们必须理解所有支持的 DBMS 类型的 SQL 语法。
相反,Obevo 采用简单的方法:在你的项目中选择通过字符串搜索发现的对象名称,并假定它们是依赖项。
实现说明:
以下是我们先前示例的算法结果:
如果出现误报匹配(例如由于注释)或假阴,开发人员可以根据需要指定排除或包含覆盖。
乍一看,可能很难想象这适用于实际用例,但我们已经成功地使用了这种技术来部署许多复杂的 schema ,其中一些跨越数千个对象,如表、存储过程、视图等。
想看实例的话请查看我们的 kata 课程,该课程是个通过一个大型数据库 schema 反向工程的示例。
跨多个表处理数据迁移
我们快速过一下这种用法(即将数据从旧列移动到新列,然后删除旧列),因为最开始将基于对象的文件结构概念应用于此听起来更复杂。
Obevo 可以处理这个问题 - 简而言之,我们提供了「迁移」对象的概念来帮助解决此问题,它:
如需更多信息,请查看 文档。
现有数据库 schema 的逆向工程
希望我们成功展示了你可以使用 Obevo 部署复杂的数据库 schema 。但是,为了让现有系统真正加入到 Obevo 中,我们必须使开发人员能够轻松地对现有数据库进行逆向工程。
解决这个问题并不容易,因为不幸的是,在不同的 DBMS 类型之间没有一个完美的统一 API
因此,我们选择与供应商提供的反向工程工具集成(见下表)。一些工具只需将完整架构输出到单个文件中即可,但我们提供了一个实用程序,可以将这些文件转换为 Obevo 基于对象结构,并利用简单字符串解析和正则表达式技术。相比 Java API,我们认为这种技术更可靠于现有系统中,特别是核心供应商工具最懂得他们自己架构。
数据库管理系统
结论
虽然有许多开源工具可用于数据库部署,但我们认为更复杂的使用情况需要更强大的工具支持。
通过 Obevo,我们旨在支持所有类型的系统;无论是通过测试功能和易于基于对象维护来增强现代系统的生产力,还是通过促进长期存在但以前没有 SDLC 管控的系统加入管控重获新生。
这里还有更多未涉及到的特性和数据库部署活动(例如回滚、分阶段部署、内存 DB 测试、多 schema 管理)。欢迎访问我们的 Github,文档和 Kata 课程,了解更多关于 Obevo 以及如何将该工具应用到你的系统中。
Bytebase 团队的读后感
通过解读高盛如何变更数据库的案例,我们可以一窥企业级数据库变更的复杂度。这篇文章的精华在于当中对于数据库变更工具设计方案选择的亮点归纳:
Obevo 相比于业界其他的工具,在这两点上都选择了非主流,但是可以更加自动化的方案:
对于高盛来说这是可行的,因为在一个单一组织内,可以通过各种约束,保证操作的一致性,然后基于这样的统一,提高自动化。但是如果要作为一个对外输出的方案,就未必能应付不同组织不同的操作习惯。 Bytebase 团队接触到 Obevo 也是一个潜在客户在调研各种方案时聊起的。相比于 Obevo 而言,Bytebase 提供的是数据库变更,查询,安全,治理一体化方案,而且还提供了可视化界面。
你可以访问 官网,免费注册云账号,立即体验 Bytebase。
求大智慧或同花顺“假阴真阳”主图源码
STICKLINE(C<O AND C>REF(C,1),H,L,0,0)COLORMAGENTA;
STICKLINE(C<O AND C>REF(C,1),O,C,3,0)COLORMAGENTA;
上面的是主图的
V,VOLSTICK;
STICKLINE(C<O AND C>REF(C,1),0,V,3,0)COLORMAGENTA;
上面是副图,要不要把均线指标加进去