暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【实战案例】磐维数据库_关于序列前跳和回退的现象分析

原创 磐维数据库 2025-06-27
266

案例背景

      某省磐维分布式数据库。


环境描述

      OS :bclinux-euler 21.10

      数据库版本:PanweiDB_V2.0_S3.0.1_B01

      兼容模式:A

      数据库架构:分布式


描述

      某省磐维分布式业务数据库变成只读, 业务进程在8点25分进行了重启操作。重启后发现从数据库取 JD.I_DATA_INDEX_SUB_SEQ 的seq 进行了回退,回退成之前的seq。导致业务进程无法按序列处理,部分工单积压 延迟处理大概10~20分钟。在9点前业务已经全部恢复。

      历史问题记录:3月30日首次发现该问题现象时耗时超过2小时,业务侧进行业务重批补救问题。

      分析日志发现应用重启后要重新从数据库中取seq_id,此时取到的JD.I_DATA_INDEX_SUB_SEQ开始 为124949050,而之前还是1253开头的序列,所以导致信管无法按序处理,导致工单延迟。


重启前:seq为1253XXX


重启后:seq回退到了1249XXX


此后业务对dn进行重启测试准备复现问题,在这个dn节点恢复后,查看日志发现应用取到的Sequence从76996622跳到了77164610。


分析

      序列Sequence是用来产生唯一整数的数据库对象。序列的值是按照一定规则自增的整数。因为自增所以不重复, 因此说Sequence具有唯一标识性。这也是Sequence常被用作主键的原因。

      通过查看序列定义,发现此序列的cache设置为4000,现场业务通过连接池并发访问数据库。每个数据库会话首次获取序列号时,当前会话会缓存4000个序列号,比如1-4000,其他会话获取序列号会缓存4001-8000,8001-12000。 业务程序使用连接池访问数据库并获取序列值,每次尝试获取序列号时,从连接池获取数据库会话,每次取到的会话不同,则会在不同的区间里获取序列值,因此会出现序列值的前跳或者回退。

序列缓存的工作原理

当设置cache n时:

● 磐维数据库会一次性获取n个序列值并缓存在内存中

● 后续请求直接从内存获取,提高性能

● 当缓存用尽时,再获取下一批n个值

并发环境下可能的问题

● 序列不连续

   不同会话可能获取不同批次的序列值,导致整体不连续

   例如:会话A获取 1-100,会话B获取101-200,实际使用顺序可能是1,101,2,102... 

● 事务回滚导致的空洞:

   即使事务回滚,已获取的序列值也不会回滚

   导致序列值出现"空洞"

● 服务器崩溃导致的序列值丢失:

   已缓存但未使用的序列值在服务器崩溃后会丢失 

   下次启动后从丢失位置后继续分配

● 分布式环境下的更大间隔:

   在流复制或分布式环境中,序列值可能会有更大的间隔

何时可以使用缓存序列

缓存序列适合以下场景:

● 不要求严格连续的序列值

● 高性能是关键需求

● 序列值仅用作唯一标识,不表示顺序

● 业务能容忍少量序列值丢失

何时应避免使用缓存序列

不应使用缓存序列的场景:

● 需要严格连续的订单号、发票号等

● 序列值作为业务逻辑的一部分(如按序号处理)

● 需要严格无空洞的ID分配

最佳实践建议

1. 评估业务需求

     如果只是需要唯一ID,缓存序列是安全的

     如果需要严格连续,使用CACHE 1

2. 考虑替代方案

      UUID作为唯一标识且不涉及排序的

      使用时间戳+随机数组合

      应用层生成的ID

3. 调整缓存大小

      根据并发量和性能需求平衡

      一般建议CACHE 20-100对大多数应用是合理的

在大多数业务场景中,使用适当大小的序列缓存(CACHE 20-100)是安全且能显著提高性能的,只要业务不依赖序列值 的严格连续性。

若业务获取序列值不是非常频繁,且有严格的排序需求时,建议关闭改序列的cache

关于在oracle库中的区别探讨:

业务反馈在Oracle库中没有出现过类似情况,这是由于Oracle里面SEQUENCE的缓存是实例级别的,他们是实例内共享的,但是磐维数据库里面SEQUENCE的缓存是会话级别的,所以在磐维数据库中高并发下取SEQUENCE就可能会出现跳变的可能。


结论

      业务现场 sequences 跳变和回退是由于序列开启了 4000 的cache,且同时使用了连接池技术,不同的连接池有不同的缓存空间,这样业务故障后重连数据库连接池连到不同的会话连接,此会话连接不同于故障时的序列缓存,所以造 成了大幅度的回退或者跳变。

      序列缓存有两种方式,可通过服务器缓存,也可以通过客户端进行缓存。所以现场问题建议业务将cache关闭,使用客户端缓存以解决序列性能问题。

ALTER SEQUENCE XXX  CACHE 1;

最后修改时间:2025-06-27 18:17:31
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论