• PostgreSQL在不同的表空间移动数据文件


    一、背景

    在工作中,可能会遇到将表从一个表空间移动另一个表空间。例如

    * 对数据进行冷处理
    * 表空间所在的磁盘空间不足
    * 建表时分配错了表空间
    

    以上等等,可能需要你将一个表移动表空间。

    二、表空间介绍

    PostgreSQL的表空间

    三、移动数据文件方法

    我们先打造下环境;创建两个表空间

    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)
    

    3.1、alter table

    将表从一个表空间移到另一个表空间

    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操作一直处在等待。那有没有不锁表,或者锁表的时间极短的方法呢?

    3.2、create + copy

    我们想想,在做表的移动表空间操作步骤可以理解是,

    新建一个表在tsp02中,再把数据copy过来,再用新表替换旧表。该方式操作太复杂了,同时也不能保证数据的完整性。在确保在这段时间内不对表进行任何操作;可以试下。

    3.3、pg_repack

    在生产环境处理表膨胀,我们会考虑用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)
    

    限制之处:

    1. 执行pg_repack操作需要超级用户
    [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
    
    1. 移动的表需要有主键或者唯一索引;这个取决于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
    
  • 相关阅读:
    C# 中的本地函数
    C# 9.0 正式发布了(C# 9.0 on the record)
    如何禁用控制台窗口的关闭按钮?
    在 WSL Ubuntu 上使用 .NET 进行跨平台开发新手入门
    C# 中 ConcurrentDictionary 一定线程安全吗?
    Docker 与 Podman 容器管理的比较
    C# 中的数字分隔符 _
    C# 8: 可变结构体中的只读实例成员
    C# 中的只读结构体(readonly struct)
    C# 8: 默认接口方法
  • 原文地址:https://www.cnblogs.com/lottu/p/13597854.html
Copyright © 2020-2023  润新知