今天我在恢复一个PostgreSQL数据库后发现一个奇怪的行为:所有serial
字段默认值的模式都被修剪掉了。
例如:
CREATE TABLE testschema.testtable
(
id serial,
name character varying(255),
CONSTRAINT pk_testtable PRIMARY KEY (id)
)
WITH (
OIDS = FALSE
)
;
SELECT a.attnum, n.nspname, c.relname, d.adsrc AS default_value
FROM pg_attribute AS a
JOIN pg_class AS c ON a.attrelid = c.oid
JOIN pg_namespace AS n ON c.relnamespace = n.oid
LEFT OUTER JOIN pg_attrdef AS d ON d.adrelid = c.oid AND d.adnum = a.attnum
WHERE a.attnum > 0
AND n.nspname = 'testschema'
AND c.relname = 'testtable'
Run Code Online (Sandbox Code Playgroud)
该id
的DEFAULT_VALUE是nextval('testschema.testtable_id_seq'::regclass)
。
恢复后,default_value 更改为nextval('testtable_id_seq'::regclass)
并且 INSERT 开始失败,因为在其架构上找不到序列。
备份
$ pg_dump -F c -Z 9 -b -h localhost -U postgres -f backup dbname
恢复
$ pg_restore -U postgres -h localhost -l backup > backup.list
$ pg_restore -U postgres -h localhost --disable-triggers -O -d dbname -S postgres -Fc -L backup.list backup
这是一些备份/恢复问题吗?我究竟做错了什么?顺便说一句,PostgreSQL 版本是 9.1.3 x64 运行在 Windows(开发机器)上,但也可以在 Linux 上复制。
我运行了与您相同的过程,但得到了不同的结果。当尝试覆盖同一数据库时,使用命令恢复数据库不起作用,因为您没有使用 -c --clean 选项。使用相同的 pg_restore 命令恢复到新数据库是有效的。然而插入新记录仍然是可能的。
这是我采取的步骤。
创建数据库
createdb testdatabase
创建架构
psql -d testdatabase -c 'create schema testschema;'
创建表
psql -d 测试数据库
CREATE TABLE testschema.testtable(
id serial, name character varying(255),
CONSTRAINT pk_testtable PRIMARY KEY (id)
) with (OIDS=false);
Run Code Online (Sandbox Code Playgroud)
注意:CREATE TABLE 将为串行列“testtable.id”创建隐式序列“testtable_id_seq” 注意:CREATE TABLE / PRIMARY KEY 将为表“testtable”创建隐式索引“pk_testtable” CREATE TABLE
插入一些记录
testdatabase=# insert into testschema.testtable (name) values('person1'),('person2');
INSERT 0 2
Run Code Online (Sandbox Code Playgroud)
备份数据库
pg_dump -F c -Z 9 -b -h localhost -U postgres -f backup testdatabase
Run Code Online (Sandbox Code Playgroud)
创建备份列表文件
pg_restore -U postgres -h localhost -l 备份 > backup.list
backup.list相关内容
第2639章 1262 16468 数据库 - 测试数据库 postgres 163;1259 16472 表 testschema testtable postgres 162; 第1259章 16470 序列测试架构 testtable_id_seq postgres 2643; 0 0 testschema testtable_id_seq postgres 2644 拥有的序列;0 0 序列集测试模式 testtable_id_seq postgres 2633; 2604 16475 默认测试架构 ID postgres 2636;0 16472 表数据 testschema testtable postgres 2635; 2606 16477 约束 testschema pk_testtable postgres
恢复备份
pg_restore -U postgres -h localhost --disable-triggers -O -d testdatabase -S postgres -Fc -L backup.list backup
Run Code Online (Sandbox Code Playgroud)
pg_restore 发回错误
pg_restore:[archiver (db)] 无法执行查询:错误:模式“testschema”已存在 pg_restore:[archiver (db)] 来自 TOC 条目 163 的错误;1259 16472 表 testtable postgres pg_restore: [archiver (db)] 无法执行查询: 错误: 关系“testtable_id_seq”已存在
恢复到另一个数据库
createdb testdatabase2
pg_restore -U postgres -h localhost --disable-triggers -O -d testdatabase2 -S postgres -Fc -L backup.list backup
Run Code Online (Sandbox Code Playgroud)
没有收到任何错误
插入更多记录
psql -d testdatabase2
testdatabase2=# insert into testschema.testtable (name) values('person2'),('person3');
INSERT 0 2
Run Code Online (Sandbox Code Playgroud)
查看记录
testdatabase2=# select * from testschema.testtable;
id | name
----+---------
1 | person1
2 | person2
3 | person2
4 | person3
Run Code Online (Sandbox Code Playgroud)
查看testschema.testtable的表结构
pg_dump --schema-only -t testschema.testtable testdatabase2
Run Code Online (Sandbox Code Playgroud)
正如您在问题中提到的,postgresql 确实重写了默认值
ALTER TABLE ONLY testtable ALTER COLUMN id SET DEFAULT nextval('testtable_id_seq'::regclass);
结论
使用完全相同的命令,尝试恢复同一数据库时确实会发生错误,但恢复到新数据库时,可以添加新记录。
您必须添加 -c 或 --clean 来删除现有对象,以便可以通过 pg_restore 恢复它们。
pg_restore -c -U postgres -h localhost --disable-triggers -O -d testdatabase -S postgres -Fc -L backup.list backup
Run Code Online (Sandbox Code Playgroud)
正如您在问题中提到的那样,Postgresql 确实重写了串行列的默认值,但插入仍然是可能的。
更新答案
使用您提供的查询时,确实在恢复数据库后我在搜索路径中没有看到测试模式。
testdatabase=# SELECT a.attnum, n.nspname, c.relname, d.adsrc AS default_value FROM pg_attribute AS a JOIN pg_class AS c ON a.attrelid = c.oid JOIN pg_namespace AS n ON c.relnamespace = n.oid LEFT OUTER JOIN pg_attrdef AS d ON d.adrelid = c.oid AND d.adnum = a.attnum WHERE a.attnum > 0 AND n.nspname = 'testschema' AND c.relname = 'testtable';
attnum | nspname | relname | default_value
--------+------------+-----------+---------------------------------------
1 | testschema | testtable | nextval('testtable_id_seq'::regclass)
2 | testschema | testtable |
Run Code Online (Sandbox Code Playgroud)
但是,当我使用 \d testschema.testtable 时,我确实在 NEXTVAL 的定义中看到了 testschema
testdatabase=# \d testschema.testtable;
Table "testschema.testtable"
Column | Type | Modifiers
--------+------------------------+-------------------------------------------------------------------
id | integer | not null default nextval('testschema.testtable_id_seq'::regclass)
name | character varying(255) |
Run Code Online (Sandbox Code Playgroud)
我在 Postgresql 论坛上找到了这个,其中讨论了我们都看到的差异。
http://archives.postgresql.org/pgsql-admin/2009-06/msg00070.php
归档时间: |
|
查看次数: |
3228 次 |
最近记录: |