我第一次在千万级用户系统中使用GaussDB序列时,曾遇到过一个典型性能问题:每到促销活动高峰期,订单表的序列号获取就会成为系统瓶颈。通过监控发现,每秒序列请求量超过5000次时,数据库响应时间明显上升。这正是深入理解CACHE机制的契机。
CACHE参数的本质是预分配机制。当设置CACHE 100时,数据库会一次性在内存中保留100个序列值,应用程序获取序列时直接从内存读取,而不需要频繁访问磁盘。这就像超市提前打包好的"商品组合",比临时拣货效率高得多。在高并发场景下,合理设置CACHE值能显著降低I/O竞争。实测显示,当CACHE从默认值1调整为1000时,序列获取的TPS(每秒事务数)提升了近40倍。
但缓存也不是越大越好。我曾见过将CACHE设为10000的配置,结果服务器重启后出现大量序列号空洞。这是因为缓存的序列值在内存中尚未使用就会丢失。建议根据业务峰值设置合理值:
具体配置时需要结合序列使用频率和服务器内存情况。这里有个实用技巧:通过pg_sequences视图监控序列使用情况:
sql复制SELECT seqname, cache_size, last_value
FROM pg_sequences
WHERE seqowner = current_user;
很多开发者容易忽略OWNED BY这个宝藏参数。在电商系统开发中,我们曾因疏忽导致数百个无用序列堆积在数据库中——这些序列原本是为已删除的测试表创建的。直到某天收到磁盘空间告警,才意识到问题的严重性。这正是OWNED BY参数的价值所在。
OWNED BY实现了序列生命周期自动化管理。当执行ALTER SEQUENCE seq_name OWNED BY table_name.column_name后,会出现两个关键变化:
实际项目中,我推荐两种典型使用模式:
模式一:主键序列自动化管理
sql复制-- 创建用户表
CREATE TABLE users (
user_id bigint PRIMARY KEY,
username varchar(50) NOT NULL
);
-- 创建专属序列并绑定
CREATE SEQUENCE users_id_seq START WITH 1001 OWNED BY users.user_id;
-- 设置默认值
ALTER TABLE users ALTER COLUMN user_id
SET DEFAULT nextval('users_id_seq');
模式二:多租户ID隔离
sql复制-- 为每个租户创建专属序列
CREATE SEQUENCE tenant_1_order_seq OWNED BY orders.order_id;
CREATE SEQUENCE tenant_2_order_seq OWNED BY orders.order_id;
-- 应用层根据租户选择序列
INSERT INTO orders (order_id, ...)
VALUES (nextval('tenant_' || current_tenant() || '_order_seq'), ...);
特别注意:OWNED BY只建立管理关系,不会自动设置默认值。需要额外执行ALTER TABLE设置默认值,这是新手常踩的坑。
在银行核心系统迁移到GaussDB分布式版时,我们遇到过序列跳号的问题:批处理任务获取的序列区间(10001-10050)因事务回滚导致实际只使用了20个,剩余的30个号码永久丢失。在金融领域,这种序列不连续可能引发审计风险。
通过实践总结出以下分布式序列最佳实践:
方案一:事务内谨慎使用序列
sql复制BEGIN;
-- 先获取序列值再执行业务操作
SELECT nextval('txn_seq') INTO txn_id;
INSERT INTO transactions (id, ...) VALUES (txn_id, ...);
-- 其他业务操作
COMMIT;
方案二:使用WITHOUT OVERLAPS避免区间冲突
sql复制CREATE SEQUENCE distributed_seq
START WITH 1
INCREMENT BY 50
MINVALUE 1
MAXVALUE 9223372036854775807
CACHE 1
NO CYCLE
WITHOUT OVERLAPS;
方案三:全局序列服务设计
对于严格要求连续的场景,可以构建中央序列服务:
在数据迁移场景中,要特别注意序列值的同步。我们开发过迁移工具专门处理这个问题:
生产环境中,序列可能成为最隐蔽的性能杀手。曾有一次系统卡顿,排查两小时才发现是某个序列的CYCLE配置导致。自此我们建立了完整的序列监控体系:
关键监控指标:
监控SQL示例:
sql复制SELECT
s.sequence_name,
s.start_value,
s.minimum_value,
s.maximum_value,
s.increment,
s.cycle_flag,
s.cache_size,
s.last_value,
round((s.last_value-s.start_value)*100.0/(s.maximum_value-s.minimum_value),2) as usage_percent,
pg_sequence_last_value(s.sequence_schema, s.sequence_name) as actual_last_value
FROM
information_schema.sequences s
WHERE
s.sequence_schema NOT IN ('pg_catalog', 'information_schema');
常见异常处理方案:
ALTER SEQUENCE seq_name RESTART WITH重置序列在金融级应用中,我们还实现了序列熔断机制:当序列使用率达到90%时自动触发告警,超过95%时自动扩展序列范围。这套机制在多次大促活动中发挥了关键作用。