关系型数据库模型的承诺与现实
关系型模型——以预定义类型列构成的表,以及表间交叉引用——是计算机科学和实际部署中最古老且存续至今的模型之一。软件领域的演进通常会淘汰旧的模型,因此关系型模型的持续存在表明它的合理性、实用性以及稳固性。关系型模型帮助我们将数据组织为元素及其属性,并通过关联不同的元素使数据更具结构化。
随着关系型模型而来的是SQL——一种声明式语言,其表达能力足以回答从简单到复杂的各类数据查询问题。SQL对于DBA(数据库管理员)、开发者、数据科学家、分析师等来说都非常熟知。无论是关系型数据库还是流行的非关系型数据库中,SQL及其变体均随处可见。
然而,关系型模型也存在不足之处,这些问题更多地体现在运营层面:虽然数据库系统优化了读取和写入的性能,但对于元数据的变更、尤其中最具体的模式(schema)变更却缺乏优化。模式变更面临各种挑战,其中最显著的问题是,它需要额外的运营工作,这超出了开发者的掌控范围。
我认为模式管理问题是导致开发者从关系型模型转向NoSQL解决方案的一个重要原因。
这种情况存在着其历史背景。早些时候,模式变更并不那么频繁。当时还没有互联网,产品版本的迭代通常需要数月。DBA通常充当数据库的“守门人”角色,负责确保模式的有效性和查询性能,同时仔细审查任何模式变更的申请。进行变更的流程通常需要不同部门间的讨论。模式变更本身也不处于数据路径中。例如,团队会在计划好的维护时间内将系统下线,执行一系列模式变更,然后将系统恢复上线,每隔几个月重复一遍这种流程。
但现在时代已经改变。产品以互联网服务的形式交付。停机维护已经不被广泛接受。我们已经进入持续部署的时代,开发的速度和频率也不断提升。如今,流行的服务一天内运行多次模式迁移也不足为奇。角色发生了变化:如今的DBA更多是“赋能者”;除了继续确保数据库服务的可靠性和高性能之外,还帮助开发者高效工作,满足他们的需求。
然而,尽管关系型数据库系统已经演进以应对现代流量需求,但这些系统在满足开发人员需求方面的进展却不够显著。问题在于,为开发者提供所需的开发速度时,关系型数据库(RDBMS)仍然是他们面前的一道障碍。
首先,开发者需要更深刻地理解数据库行为,包括元数据锁定及迁移操作可能引发的运营问题,例如锁定、资源耗尽、复制延迟等。
其次,开发者需要有权限运行模式变更操作。他们需要识别生产环境中表所在的位置,确定哪些具体服务器作为主库。在MySQL领域,人们通常会使用第三方工具,如gh-ost或pt-online-schema-change,这些工具通过模拟和替换实现在线模式变更。但要使用这些工具,开发人员需要访问生产系统,并且还需要了解如何调用这些工具、配置限流、监控进度以及清理工具产生的工件。
开发者还需要能够处理各种错误,包括内部数据库错误、工具错误,甚至是迁移过程中发生的主库故障切换场景。
除此之外,模式变更还需要协调和调度。通常不希望同时运行多个变更。开发者需要彼此同步,优先排序工作。而数据库系统本身并未提供自动化的流程,也没有类似于代码版本控制和冲突解决的机制来支持开发者。
上述运营方面的复杂性,以及协同变更的需求,使DBA重新成为数据库的“守门人”。这一次角色成为一种强制性的约束,负责充当协调者、问题和错误的解决者、模式变更的调度员。对于初创公司,这种运营复杂性可能影响不大,但随着业务规模的增长,协调和实施模式变更的角色需求愈发明显。
因此,开发者不再完全拥有他们所提交的模式变更。开发者需要提交工单,吸引某人的注意力,信任某人去执行模式变更,并跟进更新。我见过开发者采取以下路径以规避这种繁琐的过程:
- 推迟开发,汇聚多个变更到一次部署中。
- 在无模式的JSON列中过度填充内容。
- 避免模式变更,以非最优方式调整代码。
- 离开关系型数据库,转向文档数据库,牺牲RDBMS的优势以加速开发部署。
对于许多开发者来说,RDBMS的模式变更是一种异类操作。这与代码部署的形式截然不同,没有提供开发者对于代码修改所习惯的自动化级别。它缺乏快速开发中的冲突解决机制。对生产的风险较高,并且数据库系统不提供撤销变更的功能。
以上种种问题是我们在开发PlanetScale时重点关注的内容。我们相信关系型模型是稳固的,并认为降低其操作复杂性至关重要。我们想要创造一种对开发者更友好的体验,同时让开发者能够重新完全掌控他们的操作。我们认为这种体验能够让开发者感到愉悦。
关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台
除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接