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

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

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

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