V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NoKey
V2EX  ›  程序员

后端服务在有数据库变更的情况下,如何不停服务发版

  •  1
     
  •   NoKey · 2023-05-11 15:37:17 +08:00 · 3763 次点击
    这是一个创建于 560 天前的主题,其中的信息可能已经有所发展或是发生改变。
    请教大家一个问题
    比如我们后端服务器有 5 台,数据库是同一个
    新版本要发布了,有数据库变更,比如我们把某个字段去掉了,或者改了名等
    那么在发版前,需要先执行变更 sql ,这个 sql 一执行,就会影响所有服务
    那么所有服务必须跟着都发版才行
    否则部分功能会因为 sql 变更了执行失败
    无法做到部分先升级验证,验证 ok 再升级剩下的
    请假一下,有啥比较完善的方式处理这个问题呢,谢谢~
    29 条回复    2023-05-12 16:35:03 +08:00
    garylikira
        1
    garylikira  
       2023-05-11 15:41:19 +08:00
    mysql 的话有个 gh-ost , 有 online ddl 模式。具体原理没了解过。好像本质就是先建立幽灵表,然后 copy 原始数据到幽灵表,然后 rename 原始表名字到幽灵表
    EmiliatanTenshi
        2
    EmiliatanTenshi  
       2023-05-11 15:49:33 +08:00   ❤️ 1
    类似的问题都可以抽成两种变更:
    1. 新增字段
    2. 删除字段。
    EmiliatanTenshi
        3
    EmiliatanTenshi  
       2023-05-11 15:52:12 +08:00   ❤️ 1
    @EmiliatanTenshi 快捷键直接提交回复了。
    1.新增字段。这种变更先变更 db ,再升级服务,保证字段可空就不会有问题
    2. 删除字段。这种变更先把在线服务对待删除字段的依赖去除,再操作 db 变更,也可以保证兼容性。
    至于修改字段这种,在我经历过的几家公司都是禁止的,原因就是在线无法保证兼容性。但也不是完全无解,可以新增一个新字段,把历史数据及增量数据都写到新字段上,再把老字段下线,相当于拆解成了一个删除字段和一个新增字段的操作。不过问题就是涉及历史数据比较麻烦
    brader
        4
    brader  
       2023-05-11 15:52:29 +08:00
    你应该在代码开发上就要考虑兼容了。如果无法平滑过渡的,你就在新开发的接口里面,加一些版本判断的代码
    sujin190
        5
    sujin190  
       2023-05-11 15:56:03 +08:00   ❤️ 2
    如果你要平滑升级,那么数据结构就要支持平滑升级啊,比如这种修改字段的需要升级两个版本才能完成,第一版添加心字段并且修改业务逻辑同时兼容新老字段使用,第二版删除老字段同时业务逻辑删除对老字段的使用和支持,一劳永逸的方法肯定是没有的,否则大家废了吧劲的搞设计模式搞业务抽象搞微服务干嘛呢
    Anivial
        6
    Anivial  
       2023-05-11 16:02:09 +08:00
    你这种情况属于多个服务都能更改同一数据库同一表的数据,最好是每个服务的数据都分离,公用的数据上再建立一个服务对外提供接口
    LeegoYih
        7
    LeegoYih  
       2023-05-11 16:10:04 +08:00
    兼容处理平滑过渡
    半夜人少的时候发布

    删字段 /表,改字段名 /表名是什么逆天操作,保留着又不影响你干活
    我以前维护一个老项目,一堆 typo 和弃用字段,凑合用就完事了,实在不行就跳槽
    zsc8917zsc
        8
    zsc8917zsc  
       2023-05-11 16:11:48 +08:00
    为啥要删字段。。统一都是新增字段
    koloonps
        9
    koloonps  
       2023-05-11 16:12:31 +08:00
    “改了名” 用数据库视图
    opengps
        10
    opengps  
       2023-05-11 16:22:07 +08:00
    按照开闭原则去做,改字段原则上是不允许的。如果确实必要,可以用“现在加字段+后期减字段”模式
    Masoud2023
        11
    Masoud2023  
       2023-05-11 16:30:58 +08:00
    你这个问题就不应该出现,生产环境为什么要删字段或者改字段名?
    seers
        12
    seers  
       2023-05-11 16:31:59 +08:00 via Android
    你们验证就不能去测试环境吗
    killva4624
        13
    killva4624  
       2023-05-11 16:34:36 +08:00
    字段去掉或者改名也太逆天了...
    1 、 在服务里做兼容,先升级服务,再 sql 变更;记得做好数据库备份,万一不兼容可以回滚。
    2 、如果可以禁写操作的话,就弄一套完全一样的服务+数据库,把流量先切过去,原库+原服务变更好了再一点点切回来。
    brust
        14
    brust  
       2023-05-11 16:41:17 +08:00
    你做减量 sql 发版不怕回退版本吗?
    h82258652
        15
    h82258652  
       2023-05-11 16:45:09 +08:00
    绝大部分项目都可以深夜停机吧。反正我以前就是停服务,更新数据库,更新服务,启动服务,写好脚本,一套下来也就几十秒。
    brust
        16
    brust  
       2023-05-11 16:46:51 +08:00
    有 sql 版本控制的
    比如 java 可以用 flyway
    crazyweeds
        17
    crazyweeds  
       2023-05-11 16:52:19 +08:00
    肯定可以,就是成本有点高。从数据库层面而言,你创建一个新表,把旧表数据实时同步过去,新服务用新表即可。这就实现了新老服务互不干涉。
    cyningxu
        18
    cyningxu  
       2023-05-11 17:54:58 +08:00
    “比如我们把某个字段去掉了”:先把 5 台机器都上线后,再删除字段。
    “或者改了名”:假定 A 改名为 B ,先新增 B ,代码中取值时要新增找不到 B 字段则使用 A 字段兜底的逻辑,写值时要新增 A 字段存在时 AB 双写,A 不存在则仅写 B 的逻辑,待 5 台机器都上线后,删除 A 字段即可。下次升级版本再去掉 A 字段的冗余逻辑。
    Dogtler
        19
    Dogtler  
       2023-05-11 18:30:33 +08:00
    要不复制新表出来再用切换表的方式发布版本?大概是起个 tmp 的作用。
    yazinnnn
        20
    yazinnnn  
       2023-05-11 18:38:38 +08:00
    改名确实有点逆天
    fantathat
        21
    fantathat  
       2023-05-11 18:58:17 +08:00 via iPhone
    厨房炸了锅,餐厅还能出来菜,神奇
    xuelu520
        22
    xuelu520  
       2023-05-11 19:01:36 +08:00
    第一次见已上线的服务改字段名的。
    Pantheoon
        23
    Pantheoon  
       2023-05-11 19:04:48 +08:00
    第一次见已上线的服务删字段的
    sadfQED2
        24
    sadfQED2  
       2023-05-11 19:11:14 +08:00 via Android
    第一次见已上线的服务发版不考虑兼容的
    ytmsdy
        25
    ytmsdy  
       2023-05-11 19:38:11 +08:00
    还是老老实实停服务吧!涉及到改字段,好像都没法完美处理。
    huzhizhao
        26
    huzhizhao  
       2023-05-12 08:16:43 +08:00
    改名字是因为闲着了吗
    xxmaqzas
        27
    xxmaqzas  
       2023-05-12 10:54:30 +08:00
    只增不删改(等服务运行稳定在统一把不用的字段删除?历史数据问题,不建议删除)
    zagfai
        28
    zagfai  
       2023-05-12 16:34:03 +08:00
    这种平滑升级是一个很复杂的过程,都是按月为单位的变更。可以多库多表多写多读之类的方法,分步骤切换。
    zagfai
        29
    zagfai  
       2023-05-12 16:35:03 +08:00
    至于说 online ddl ... 还是小心使用,基本没试过不出问题:—)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3339 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 04:57 · PVG 12:57 · LAX 20:57 · JFK 23:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.