时间:2020-09-01来源:www.pcxitongcheng.com作者:电脑系统城
在工作中,可能会遇到将表从一个表空间移动另一个表空间。例如
* 对数据进行冷处理 * 表空间所在的磁盘空间不足 * 建表时分配错了表空间
以上等等,可能需要你将一个表移动表空间。
我们先打造下环境;创建两个表空间
postgres=# CREATE TABLESPACE tsp01 OWNER lottu LOCATION '/data/pg6000/tsp01'; CREATE TABLESPACE postgres=# CREATE TABLESPACE tsp02 OWNER lottu LOCATION '/data/pg6000/tsp02'; CREATE TABLESPACE
查看数据库默认表空间
postgres=# \c lottu lottu You are now connected to database "lottu" as user "lottu". lottu=> select d.datname,p.spcname from pg_database d, pg_tablespace p where d.datname='lottu' and p.oid = d.dattablespace; datname | spcname ---------+------------ lottu | pg_default (1 row)
接下来我们在表空间tsp01建表tbl_lottu
lottu=> create table tbl_lottu(id int primary key, info text) TABLESPACE tsp01; CREATE TABLE lottu=> insert into tbl_lottu select generate_series(1,1000) ,md5(random()::text); INSERT 0 1000 lottu=> \d tbl_lottu Table "lottu.tbl_lottu" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- id | integer | | not null | info | text | | | Indexes: "tbl_lottu_pkey" PRIMARY KEY, btree (id) Tablespace: "tsp01"
而表tbl_lottu数据文件的位置
lottu=> select pg_relation_filepath('tbl_lottu'); pg_relation_filepath --------------------------------------------- pg_tblspc/90618/PG_12_201909212/24750/90620 (1 row)
将表从一个表空间移到另一个表空间
lottu=> ALTER TABLE tbl_lottu SET TABLESPACE tsp02; ALTER TABLE
我们再查看表;已经成功移动表空间tsp02
lottu=> \d tbl_lottu Table "lottu.tbl_lottu" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- id | integer | | not null | info | text | | | Indexes: "tbl_lottu_pkey" PRIMARY KEY, btree (id) Tablespace: "tsp02" lottu=> select pg_relation_filepath('tbl_lottu'); pg_relation_filepath --------------------------------------------- pg_tblspc/90619/PG_12_201909212/24750/90629 (1 row)
不足之处:在alter table这个过程中是锁表的;若是大表;执行时间久,在这个时间内表在dml操作一直处在等待。那有没有不锁表,或者锁表的时间极短的方法呢?
我们想想,在做表的移动表空间操作步骤可以理解是,
新建一个表在tsp02中,再把数据copy过来,再用新表替换旧表。该方式操作太复杂了,同时也不能保证数据的完整性。在确保在这段时间内不对表进行任何操作;可以试下。
在生产环境处理表膨胀,我们会考虑用pg_repack来取代vacuum full,因为它在处理表膨胀的过程中可以避免表被长期锁定。pg_repack工作原理:创建一个新表,将数据从旧表移动到新表。为了避免表被独占锁定,创建了一个额外的日志表来记录原始表的改动,还添加了一个把INSERT / UPDATE / DELETE操作记录到日志表的触发器。当原始表中的数据全部导入到新表中,索引重建完毕,日志表的改动全部完成,pg_repack会连同新索引,用新表替换旧表,并将原旧表Drop掉。整个过程非常简单,非常可靠。同时它还支持在不同表空间迁移表和索引。
我们开始实际操作下:
第一步:先创建表tbl_repack;
lottu=# create table tbl_repack(id int primary key, info text) TABLESPACE tsp01; CREATE TABLE lottu=# insert into tbl_repack select generate_series(1,1000000) ,md5(random()::text); INSERT 0 1000000 lottu=# select pg_relation_filepath('tbl_repack'); pg_relation_filepath --------------------------------------------- pg_tblspc/90618/PG_12_201909212/24750/90681 (1 row)
第二步:执行pg_repack
[postgres@lottu ~]$ pg_repack -t lottu.tbl_repack -s tsp02 -j 2 -d lottu -U lottu NOTICE: Setting up workers.conns INFO: repacking table "lottu.tbl_repack"
执行的同时;我们对表tbl_repack执行delete操作;实验是否堵塞dml操作
lottu=# delete from tbl_repack where id < 100; DELETE 99
第三步:查看是否移动成功
lottu=# select pg_relation_filepath('tbl_repack'); pg_relation_filepath --------------------------------------------- pg_tblspc/90619/PG_12_201909212/24750/90704 (1 row) lottu=# \d tbl_repack; Table "lottu.tbl_repack" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- id | integer | | not null | info | text | | | Indexes: "tbl_repack_pkey" PRIMARY KEY, btree (id) Tablespace: "tsp02" lottu=# select count(1) from tbl_repack ; count -------- 999901 (1 row)
限制之处:
[postgres@lottu ~]$ pg_repack -t tbl_repack -s tsp02 -j 2 -d lottu -U lottu NOTICE: Setting up workers.conns ERROR: pg_repack failed with error: You must be a superuser to use pg_repack
[postgres@lottu ~]$ pg_repack -t lottu.tbl_repack -s tsp02 -j 2 -d lottu -U lottu NOTICE: Setting up workers.conns WARNING: relation "lottu.tbl_repack" must have a primary key or not-null unique keys
__EOF__
2022-09-11
Windows 系统 PostgreSQL 手工安装配置方法教程图解2022-02-25
系统城教小白如何在Centos8-stream安装PostgreSQL132021-04-22
自定义函数实现单词排序并运用于PostgreSQL(实现代码)