咨询PostgreSQL多端口并发创建患者时生成唯一ID的方法
PostgreSQL多并发场景下生成唯一患者ID的解决方案
针对多端口并发创建患者时MAX(id)+1导致重复ID的问题,以下是PostgreSQL环境下的可行方案,按推荐优先级排序:
1. 使用自增主键(SERIAL/IDENTITY)
这是最常用、最简单的解决方案,PostgreSQL原生支持原子性的ID生成,完全避免并发冲突。
两种实现方式:
方式一:SERIAL(PostgreSQL传统语法)
CREATE TABLE patients ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, -- 其他患者字段 );
插入数据时无需指定id,数据库会自动从内置序列中获取唯一值:
INSERT INTO patients (name) VALUES ('张三');
方式二:IDENTITY(SQL标准语法,推荐)
CREATE TABLE patients ( id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name VARCHAR(100) NOT NULL, -- 其他患者字段 );
插入逻辑和SERIAL一致,IDENTITY是SQL:2003标准,比SERIAL更规范,支持更多自定义配置(比如起始值、步长)。
原理:SERIAL/IDENTITY底层依赖PostgreSQL的序列(SEQUENCE),nextval()函数是原子操作,并发请求会依次获取唯一的序列值,不会出现重复。
2. 手动使用序列(SEQUENCE)
如果需要更灵活的ID生成规则(比如自定义起始值、步长,或多个表共用ID序列),可以手动创建序列:
-- 创建自定义序列,起始值1000,步长1 CREATE SEQUENCE patient_id_seq START WITH 1000 INCREMENT BY 1; -- 建表时关联序列 CREATE TABLE patients ( id INT PRIMARY KEY DEFAULT nextval('patient_id_seq'), name VARCHAR(100) NOT NULL );
插入时同样无需指定id,或手动调用nextval():
INSERT INTO patients (id, name) VALUES (nextval('patient_id_seq'), '李四');
3. 使用UUID生成全局唯一ID
如果你的系统是分布式架构,或需要跨实例的全局唯一ID,推荐使用UUID:
首先启用PostgreSQL的UUID扩展:
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
然后创建表:
CREATE TABLE patients ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), name VARCHAR(100) NOT NULL );
插入时自动生成UUID:
INSERT INTO patients (name) VALUES ('王五');
优缺点:UUID是全局唯一的,完全不用担心并发重复;但UUID是字符串类型,索引性能比整数ID略低,且ID不连续,不适合需要有序ID的场景。
4. 事务+行级锁(不推荐,仅用于特殊场景)
如果必须基于现有数据的MAX(id)生成连续ID,可通过事务加锁实现,但会严重影响并发性能:
BEGIN; -- 锁定patients表,防止其他事务修改 SELECT MAX(id) INTO @max_id FROM patients FOR UPDATE; INSERT INTO patients (id, name) VALUES (@max_id + 1, '赵六'); COMMIT;
缺点:FOR UPDATE会锁定整个表,并发请求会排队等待,高并发场景下性能极差,仅适合并发量极低的系统。
总结
- 优先选择自增主键(IDENTITY/SERIAL):简单、高效、原生支持,完全解决并发重复问题。
- 分布式场景选UUID:全局唯一,无需依赖数据库序列。
- 特殊规则ID选手动序列:灵活自定义生成规则。
- 锁表方式尽量避免:性能瓶颈明显。
内容的提问来源于stack exchange,提问作者user22441691
相关产品推荐
相关产品推荐

