SEQUENCE(例如,在PostgreSQL和Oracle中)是数据库中特殊的对象,存储当前值,允许获取唯一数字以进行插入(通常是键)。 IDENTITY是字段的属性,在插入时自动分配下一个顺序值(SQL Server、MySQL、PostgreSQL中的表自动增量)。
主要区别:
SEQUENCE — 是一个表外的对象,可以从不同地方访问,允许在不插入的情况下获取下一个值(nextval / currval)。可以用于多个表,可能有多个SEQUENCE对应一个表。IDENTITY — 是列定义的一部分,仅在插入行时自动增加。示例:
-- PostgreSQL SEQUENCE CREATE SEQUENCE order_seq; INSERT INTO orders(id, name) VALUES (nextval('order_seq'), '第一订单'); -- PostgreSQL IDENTITY CREATE TABLE users ( id BIGSERIAL PRIMARY KEY, username TEXT ); INSERT INTO users(username) VALUES ('ivan'); -- id将自动分配
问题和细节:
如果同时有两个请求从同一个SEQUENCE请求nextval(),会发生什么?可能会得到非唯一的值吗?
答案: 不会,SEQUENCE保证唯一性。即使在同时访问的情况下,每个请求也会获得唯一值。然而,由于并发,顺序可能与插入顺序不符。
示例:
-- 第一个线程获得nextval=100,第二个线程片刻后获得nextval=101。 -- 即使之后第一个线程回滚,值100已被使用。
事件#1
从MySQL迁移到PostgreSQL后,忘记了SEQUENCE和IDENTITY的区别:试图手动插入id,导致自动生成时出现“重复键”错误。最终修正,完全将键的管理转移到SEQUENCE上。
事件#2
在部分删除了带有autoincrement的表中的行后,需要“紧密”填充id范围。由于控制不当重新创建新行,导致了歧义——键与业务逻辑不一致,不得不转向单独的SEQUENCE进行控制。
事件#3
在大型OLTP系统中,由于缺乏对SEQUENCE的控制,订单号超过2,147,483,647,导致集成API发生故障,因为它未准备好处理bigint值。请求被重新实现,以控制SEQUENCE的上限值。