请教大家利用 mysql 存储过程生成规则唯一编号的方式可行吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
gibber
V2EX    程序员

请教大家利用 mysql 存储过程生成规则唯一编号的方式可行吗?

  •  
  •   gibber 2021-11-24 09:00:27 +08:00 3350 次点击
    这是一个创建于 1416 天前的主题,其中的信息可能已经有所发展或是发生改变。
    场景:
    1. 数据库是 mysql
    2. 有一张订单表在插入订单数据的时候需要生成唯一的订单编号,编号规则是当前月订单数据量的流水号
    3. 订单表数据插入的途径有后台程序和存储过程两种

    如何做到并发生成这个唯一编号呢?
    第 1 条附言    2021-11-24 10:02:39 +08:00
    补充一下:
    编号规则是当前月订单数据量的流水号
    例如:
    本月第一条数据编号为 DD202111000001
    本月第二条数据编号为 DD202111000002
    ...
    下月第一条数据编号为 DD202112000001
    下月第二条数据编号为 DD202112000002
    ...
    21 条回复    2021-11-25 16:18:48 +08:00
    banlifeather4
        1
    banlifeather4  
       2021-11-24 09:14:15 +08:00
    经验来看的话, 不管是单体服务还是分布式服务, 建议 ID 都设计成全局唯一的,增加不了多少成本;

    但是不这么搞的话,如果一旦做分表分库等,涉及的数据清洗的工作量应该够你加班 2 个月的( 1 个月,2.am 下班)
    allenzhangSB
        2
    allenzhangSB  
       2021-11-24 09:17:03 +08:00
    你这个需求, 最简单实现可以用 redis 的 incr
    bglucas
        3
    bglucas  
       2021-11-24 09:18:33 +08:00
    看起来像是分布式唯一 ID 生成问题?可以参考下 snowflake 和给予 mysql 的号段模式。
    onhao
        4
    onhao  
       2021-11-24 09:27:06 +08:00
    貌似触发器可以?但是需要警惕用了触发器后 last_insert_id() 获取不到最近插入的 ID
    https://wuhao.pw/archives/241/
    dk7952638
        5
    dk7952638  
       2021-11-24 09:33:47 +08:00
    借楼一问,现在全局 ID 的开源方案有没有比较靠谱的,最好是可以自增的那种
    jorneyr
        6
    jorneyr  
       2021-11-24 09:54:17 +08:00
    全局唯一自增:
    1. ID 生成服务 (只用一个服务,不要用集群,性能要高,分段获取,保证全局唯一递增,持久化到 DB)
    2. 每个服务需要 ID 时使用 RPC 去 ID 生成服务实时拿取,每次只拿一个 (RPC 保证效率)

    snowflake 等只能是趋势递增。
    gibber
        7
    gibber  
    OP
       2021-11-24 10:03:43 +08:00
    @allenzhangSB mysql 存储过程也可以调用 redis 吗?
    xsm1890
        8
    xsm1890  
       2021-11-24 10:34:33 +08:00
    可行。但如果只是用 mysql 的存储过程生成的话,这个点可能会成为系统的性能瓶颈。
    clf
        9
    clf  
       2021-11-24 10:34:41 +08:00
    在 github 上好像有 snowflake 的 mysql 存储过程实现?(没写过 mysql 的存储过程)可以考虑使用 snowflake 生成的 ID 作为主键。

    @dk7952638 #5 目前用的比较多的就是上面说的雪花算法,id bigint ,唯一需要注意的是后端序列化为 json 的时候需要把超过前端 number 范围的数值转为 string ,不然会精度丢失。
    Bigglesworth
        10
    Bigglesworth  
       2021-11-24 10:40:51 +08:00
    如果没有分库分表,业务也不大的话,虽然说全局 ID 啥的更好,但是还是按需来嘛,可以写个类似 sequence 的存储过程,后台程序和存储过程都可以调一下生成 ID ,生成规则你可以按月啥的自增。
    yidinghe
        11
    yidinghe  
       2021-11-24 11:19:01 +08:00
    参考一下这个项目:
    https://github.com/yiding-he/mysql-sequence-generator
    在数据库中建一个表,各个服务都可以并发的用这张表生成全局 ID ,原理也是利用 last_insert_id()
    jinzhongyuan
        12
    jinzhongyuan  
       2021-11-24 14:13:47 +08:00
    以前在小公司就是存储过程生成订单号
    allenzhangSB
        13
    allenzhangSB  
       2021-11-24 14:35:13 +08:00
    @gibber 没必要一定要在 MySQL 侧做吧, 代码中插入前最后一步调用下 redis 生成个序号, 插入前做好校验, 避免插入失败就可以了
    uSy62nMkdH
        14
    uSy62nMkdH  
       2021-11-24 14:49:10 +08:00
    你这种需求直接建一个仅有 ID 的表就行了吧,每次需要的时候 insert 并返回 ID 即可。如果有分库分表,在单调自增序列前加一个数据标识。
    考虑引入中间件的话,雪花、美团 leaf ,或者 zk+redis 自建。
    fengpan567
        15
    fengpan567  
       2021-11-24 15:14:21 +08:00
    snowflake 不合适吗?用存储过程,分库分表的时候不就扯淡了
    gibber
        16
    gibber  
    OP
       2021-11-24 16:25:26 +08:00
    @allenzhangSB 是的, 我知道利用 redis 很好做到唯一编号, 主要这个业务还有另外一个需求就是利用存储过程插入数据,所以要考虑到数据库端和程序同时并发
    gibber
        17
    gibber  
    OP
       2021-11-24 16:27:46 +08:00
    @uSy62nMkdH 流水号是每月重置,你说的这种方法可以实现吗?
    gavindexu
        18
    gavindexu  
       2021-11-24 20:29:18 +08:00 via iPhone
    用触发器 在插入前执行一个?
    5wunian
        19
    5wunian  
       2021-11-24 21:17:17 +08:00
    避免避免,之前的项目里是在创建的时候单独请求一个唯一 ID,创建的时候带上。虽然浪费了部分未提交的 ID ,但是避免了并发限制。
    crclz
        20
    crclz  
       2021-11-25 00:39:54 +08:00
    仅仅考虑楼主提出的需求,提出以下解决方案:

    表 X(年月 int, 流水号 int)。例如(202111, 1)

    def GenerateOrderId() -> str:
    年月 = 获取当前年月()
    num=( update 表 X set 流水号=流水号+1 returning 流水号)
    return 格式化(年月,num )

    如果数据库并发不够,可以流水号=流水号+10 之类的,然后服务端将生成的 id 全局缓存起来。

    这样做不会错的,我司就是这样干的。
    uSy62nMkdH
        21
    uSy62nMkdH  
       2021-11-25 16:18:48 +08:00
    @gibber 为什么不行呢? prefix 是自定义的,suffix 按表里的 ID 递增,两个组装起来就是你要的 ID 了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1024 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 18:32 PVG 02:32 LAX 11:32 JFK 14:32
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86