我运行一个小型站点并使用PostgreSQL 8.2.17(仅在我的主机上可用的版本)来存储数据。 在过去几个月中,我的服务器上发生了3次数据库系统崩溃,每次发生故障时,其中一个表中的串行字段(主键)发生了31个ID。现在有93个ID缺失。
表:
CREATE TABLE "REGISTRY"
(
"ID" serial NOT NULL,
"strUID" character varying(11),
"strXml" text,
"intStatus" integer,
"strUIDOrg" character varying(11),
)
对我来说,所有ID值都在那里非常重要。我该怎么做才能解决这个问题?
答案 0 :(得分:2)
你不能指望串行列没有漏洞。
你可以通过牺牲这样的并发来实现无间隙密钥:
create table registry_last_id (value int not null);
insert into registry_last_id values (-1);
create function next_registry_id() returns int language sql volatile
as $$
update registry_last_id set value=value+1 returning value
$$;
create table registry ( id int primary key default next_registry_id(), ... )
但是任何尝试向registry
表插入内容的事务都将阻塞,直到其他插入事务完成并将其数据写入磁盘。这将限制您在7500rpm磁盘驱动器上每秒不超过125个插入事务。
同样,从registry
表中删除任何内容都会产生差距。
此解决方案基于A. Elein Mustain的文章Gapless Sequences for Primary Keys,这有点过时。
答案 1 :(得分:1)
您是否缺少93条记录,或者您有31个缺失数字的3个“漏洞”?
序列不是事务安全的,它永远不会回滚。因此,不是一个系统来创建一个数字序列没有孔。
来自manual:
重要提示:避免阻塞 获得的并发事务 来自相同序列的数字,a nextval操作永远不会滚动 背部;也就是说,一旦有了价值 获取它被认为是使用,即使 执行nextval的事务 后来中止了。这意味着中止了 交易可能会闲置 分配顺序中的“孔” 值。 setval操作永远不会 退了回来。
答案 2 :(得分:-2)
感谢Matthew Wood和Frank Heikens的回答,我想我有一个解决方案。
不是使用串行字段,而是必须创建自己的序列并将CACHE参数定义为1.这样postgres不会缓存值,每个值都将直接从序列中获取:)
感谢您的帮助:)