• PG-并发问题


    1. 介绍

    PostgreSQL为开发者提供了一组丰富的工具来管理对数据的并发访问。在内部,数据一致性通过使用一种多版本模型(多版本并发控制,MVCC)来维护。这就意味着每个 SQL 语句看到的都只是一小段时间之前的数据快照(一个数据库版本),而不管底层数据的当前状态。这样可以保护语句不会看到可能由其他在相同数据行上执行更新的并发事务造成的不一致数据,为每一个数据库会话提供事务隔离。MVCC避免了传统的数据库系统的锁定方法,将锁争夺最小化来允许多用户环境中的合理性能。

    2. 并发带来的问题

    • 脏读: 一个事务读取了另一个并行未提交事务写入的数据。
    • 不可重复读: 一个事务重新读取之前读取过的数据,发现该数据已经被另一个事务(在初始读之后提交)修改。
    • 幻读:一个事务重新执行一个返回符合一个搜索条件的行集合的查询, 发现满足条件的行集合因为另一个最近提交的事务而发生了改变。
    • 序列化异常: 成功提交一组事务的结果与这些事务按照串行执行的结果都不一致。

    2.1 实验验证

    -- 设置事务隔离级别
    dev->devdb@[local]:5432=> h set transaction
    Command:     SET TRANSACTION
    Description: set the characteristics of the current transaction
    Syntax:
    SET TRANSACTION transaction_mode [, ...]
    SET TRANSACTION SNAPSHOT snapshot_id
    SET SESSION CHARACTERISTICS AS TRANSACTION transaction_mode [, ...]
    
    where transaction_mode is one of:
    
        ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
        READ WRITE | READ ONLY
        [ NOT ] DEFERRABLE
    
    -- 创建一张测试表
    CREATE TABLE tbl_mvcc (
    id serial,
    ival INT,
    PRIMARY KEY (id)
    );
    -- 插入一条测试数据
    INSERT INTO tbl_mvcc (ival) VALUES (1);
    

    2.1.1 脏读

    T1 事务连接 T2事务连接
    t1 show transaction_isolation;
    begin;
    set session transaction isolation level read uncommitted;
    show transaction_isolation;
    select * from tbl_mvcc where id = 1; /* id=l,ival=l */
    t2 begin;
    set session transaction isolation level read uncommitted;
    show transaction_isolation;
    update tbl_mvcc set ival=10 where id=1;
    t3 select * from tbl_mvcc where id = 1;
    t4 rollback;

    image-20200608154119398

    在PG没出现幻读现象。

    2.1.2 不可重复读

    T1 会话连接 T2 会话连接
    t1 BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
    SELECT id , ival FROM tbl_mvcc WHERE id= 1 ;
    t2 BEGIN ;
    UPDATE tbl_mvcc SET ival = 10 WHERE id = 1;
    COMMIT;
    t3 select * from tbl_mvcc where id = 1;
    t4 END;

    image-20200608154826842

    在上面的例子中,事务T1在tbl_mvcc表中第一次查询数据,得到id=1,ival=1的行,这时事务T2更新表中id=l的行的ival值为10,并且事务T2成功地进行了COMMIT操作。此时事务T1查询tbl_mvcc表,得到ival的值等于10,我们的预期是数据库在第二次SELECT请求的时候,应该返回事务T2更新之前的值,但实际查询到的结果与第一次查询得到的结果不同,由于事务T2的并发操作,导致事务T1不能重复读取到预期的值,这就是不可重复读的现象。

    2.1.3 幻读

    T1 会话连接 T2 会话连接
    t1 BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
    SELECT id , ival FROM tbl_mvcc WHERE id > 0 and id <10 ;
    t2 BEGIN ;
    INSERT INTO tbl_mvcc VALUES (6,6);
    COMMIT;
    t3 select * from tbl_mvcc where id = 1;
    t4 END;

    不可重复读和幻读很相似,它们之间的区别主要在于不可重复读主要受到其他事务对数据的UPDATE操作,而幻读主要受到其他事务INSERT 和 DELETE操作的影响 。

    2.1.4 序列化异常

    T1 会话连接 T2 会话连接
    t1 BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; SELECT id , ival FROM tbl_mvcc WHERE id = 1 ;
    t2 UPDATE tbl_mvcc SET ival = ival * 10 WHERE id = 1;
    t3 UPDATE tbl_mvcc SET ival = ival +1 WHERE id = 1;
    t4 ROLLBACK;

    image-20200608171448861

    在上面的例子中,事务T1开始时查询出id=1的数据,事务T2在事务T1提交之前对数据做了更新操作,并且在事务T1提交之前提交成功;当事务T1提交时,如果按照先执行T2再执行T1的顺序执行,事务T1在事务开始时查询到的数据应该是事务T2提交之后的结果:ival=10,但由于事务T1是可重复读的,当它进行UPDATE时,事务T1读到的数据却是它开始时读到的数据:ival=1;这时就发生了序列化异常的现象。Serializable与Repeatable Read在PostgreSQL里是基本一样的,除了Serializable不允许序列化异常。

    2.1.5 验证Repeatable Read 事务隔离级别不可能出现幻读

    T1 会话连接 T2 会话连接
    t1 BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
    SELECT id , ival FROM tbl_mvcc WHERE id> 3 AND id< 10 ;
    t2 BEGIN;
    INSERT INTO tbl_mvcc (id ,ival ) VALUES (6, 6);
    END ;
    t3 SELECT id , ival FROM tbl mvcc WHERE id> 3 AND 工d < 10;
    t4 END;

    image-20200608172851631

    在上面的例子中,事务T1在tbl_mvcc表中第一次查询id大于3并且小于10的数据,得到两行数据,这时事务T2在表中插入了一条id等于6的数据,这条数据正好满足事务T1的WHERE条件中id大于3并且小于10的查询条件,事务T1再次查询时,与第一次查询的结果相同,说明没有出现幻读现象。

    3. 事务隔离

    隔离级别 脏读 不可重复读 幻读 序列化异常
    读未提交 不可能 可能 可能 可能
    读已提交 不可能 可能 可能 可能
    可重复读 不可能 不可能 不可能 可能
    可序列化 不可能 不可能 不可能 不可能

    PostgreSQL内部只实现了三种不同的隔离级别,即 PostgreSQL 的读未提交模式的行为和读已提交相同。隔离级别越高,越能保证数据的完整性和一致性,但是需要更多的系统资源,增加了事务阻塞其他事务的概率,对并发性能的影响也越大,吞吐量也会更低;低级别的隔离级别一般支持更高的并发处理,并拥有更低的系统开销,但增加了并发引发的副作用的影响 。

    3.1 事务隔离级别

    • 读已提交隔离级别(Read Committed):PostgreSQL中的默认隔离级别。当一个事务运行使用这个隔离级别时, 一个查询(没有FOR UPDATE/SHARE子句)只能看到查询开始之前已经被提交的数据, 而无法看到未提交的数据或在查询执行期间其它事务提交的数据
    • 可重复读隔离级别(REPEATABLE READ):只看到在事务开始之前被提交的数据;它从来看不到未提交的数据或者并行事务在本事务执行期间提交的修改
    • 可序列化隔离级别(Serializable):提供了最严格的事务隔离。这个级别为所有已提交事务模拟序列事务执行;就好像事务被按照序列一个接着另一个被执行,而不是并行地被执行。

    3.2 事务隔离级别配置

    -- 查看全局配置
    SELECT current_setting('default_transaction_isolation');
    SELECT name, setting FROM pg_settings WHERE name = 'default_transaction_isolation';
    SELECT name, setting FROM pg_settings WHERE name ~ 'isolation';
    
    -- 2. 修改全局事务隔离级别
    -- 2.1 修改配置文件 $PGDATA/postgresql.conf 中 default_transaction_isolation 参数
    
    -- 2.2 SQL命令
    ALTER SYSTEM SET default_transaction_isolation TO 'REPEATABLE READ';
    SELECT pg_reload_conf();
    SELECT current_setting('default_transaction_isolation');
    
    
    -- 3.  修改当前事务隔离级别
    SHOW transaction_isolation;
    SELECT current_setting('transaction_isolation');
    
    -- 4. 修改当前会话事务隔离级别
    SET SESSION CHARACTERISICS AS TRANSACTION ISOLATION LEVEL READ UNCOMMITED;
    SHOW transaction_isolation;
    
    -- 5. 设置当前事务的事务隔离级别
    START TRANSACTION ISOLATION LEVEL READ  UNCOMMITED;
    START TRANSACTION
    ... /* SQL */
    END;
    
    OR
    BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
    ... /* SQL */
    END/COMMIT/ROLLBACK;
    

    4. 并发控制

    在多用户环境中,允许多人同时访问和修改数据,为了保持事务的隔离性,系统必须对并发事务之间的相互作用加以控制,在这种情况下既要确保用户以一致的方式读取和修改数据,还要争取尽量多的并发数,这是数据库管理系统的并发控制器需要做的事情。当多个事务同时执行时,即使每个单独的事务都正确执行,数据的一致性也可能被破坏。为了控制并发事务之间的相互影响,应把事务与事务在逻辑上隔离开,以保证数据库的一致性。数据库管理系统中并发控制的任务便是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性、数据的一致性以及数据库的一致性,也就是解决丢失更新、脏读、不可重复读、幻读、序列化异常的问题。

    并发控制模型有基于锁的并发控制 (Lock-Based Concurrency Control)和基于多版本的并发控制 (Multi-Version Concurrency Control。 加锁、时间戳、乐观并发控制(又名“乐观锁”, Optimistic Concurrency Control ,缩写 OCC)和悲观并发控制(又名“悲观锁”, Pessimistic Concurrency Control ,缩写为 PCC ”)是并发控制采用的主要技术手段。

    4.1 基于锁的并发控制

    PostgreSQL提供了多种锁模式用于控制对表中数据的并发访问。

    为了解决并发问题,数据库引入了“锁”的概念。
    基本的加锁类型有两种:排它锁(Exclusive locks,X锁)和共享锁(Share locks,S锁)。

    • 排它锁:被加锁的对象只能被持有锁的事务读取和修改,其他事务无法在该对象上加其他锁,也不能读取和修改该对象。
    • 共享锁:被加锁的对象可以被持锁事务读取,但是不能被修改,其他事务也可以在上面再加共享锁。

    加锁对象的大小称为加锁粒度(Granularity)。加锁的对象可以是逻辑单元,也可以是物理单元。以关系数据库为例子,加锁对象可以是这样一些逻辑单元:属性值、属性值的集合、元组、关系、索引项、整个索引项甚至整个数据库;也可以是这样的一些物理单元:页(数据页或索引页)、物理记录等。加锁的策略是一组规则,这些规则阐明了事务何时对数据项进行加锁和解锁,通常称为加锁协议(Locking Protocol)。由于采用了加锁策略,一次只能执行一个事务,所以只会产生串行调度,迫使事务只能等待前面的事务结束之后才可以开始,所以基于锁的并发控制机制导致性能低下,并发程度低。

    4.2 基于多版本并发控制

    ​ 基于锁的并发控制机制要么延迟一项操作,要么中止发出该操作的事务来保证可串行性。如果每一数据项的旧值副本保存在系统中,这些问题就可以避免。这种基于多个旧值版本的并发控制即MVCC。一般把基于锁的并发控制机制称成为悲观机制,而把MVCC机制称为乐观机制。这是因为锁机制是一种预防性的机制,读会阻塞写,写也会阻塞读,当封锁粒度较大,时间较长时并发性能就不会太好;而MVCC是一种后验性的机制,读不阻塞写,写也不阻塞读,等到提交的时候才检验是否有冲突,由于没有锁,所以读写不会相互阻塞,避免了大粒度和长时间的锁定,能更好地适应对读的响应速度和并发性要求高的场景,大大提升了并发性能,常见的数据库如Oracle、PostgreSQL、MySQL(lnnodb)都使用MVCC并发控制机制。在MVCC中每一个写操作创建一个新的版本。当事务发出一个读操作时,并发控制管理器选择一个版本进行读取。也就是为数据增加一个关于版本的标识,在读取数据时,连同版本号一起读出,在更新时对此版本号加一。

    ​ MVCC通过保存数据在某个时间点的快照,并控制元组的可见性来实现。快照记录READ COMMITTED事务隔离级别的事务中的每条SQL语句的开头和SERIALIZABLE事务隔离级别的事务开始时的元组的可见性。一个事务无论运行多长时间,在同一个事务里都能够看到一致的数据。根据事务开始的时间不同,在同一个时刻不同事务看到的相同表里的数据可能是不同的。

    ​ PG为每一个事务分配一个递增的、类型为int32的整型数作为唯一的事务ID,称为xid。创建一个新的快照时,将收集当前正在执行的事务id和已提交的最大事务id。根据快照提供的信息,PostgreSQL可以确定事务的操作是否对执行语句是可见的。PostgreSQL还在系统里的每一行记录上都存储了事务相关的信息,这被用来判断某一行记录对于当前事务是否可见。在PostgreSQL的内部数据结构中,每个元组(行记录)有4个与事务可见性相关的隐藏列,分别是xmin、xmax、cmin、cmax,其中cmin和cmax分别是插入和删除该元组的命令在事务中的命令序列标识,xmin、xmax与事务对其他事务的可见性相关,用于同一个事务中的可见性判断。

    22:01:01 [local]:5432 dev@devdb=> SELECT xmin, xmax, cmin, cmax, id, ival FROM tbl_mvcc WHERE id = 5;
     xmin | xmax | cmin | cmax | id | ival 
    ------+------+------+------+----+------
     3830 |    0 |    0 |    0 |  5 |    5
    (1 row)
    
    22:01:04 [local]:5432 dev@devdb=>
    
    /*
    * xmin: 保存了创建该行数据的事务的xid
    * xmax: 保存的是删除该行的xid
    * PostgreSQL在不同事务时间使用xmin和xmax控制事务对其他事务的可见性 
    */
    

    PG多版本优劣

    优势
    • 事务回滚可以立即完成,无论事务进行了多少操作
    • 数据可以进行很多更新,不必保证回滚段有可用空间
    劣势
    • 旧版本数据需要经常清理(vacuum)
    • 旧版本数据存储在数据文件中,可能会导致查询更慢

    4.2.1 通过xmin决定事务可见性

    当插入一行数据时,PostgreSQL会将插入这行数据的事务的xid存储在xmin中。通过xmin值判断事务中插入的行记录对其他事务的可见性。

    回滚的事务或未提交的事务创建的行对于任何其他事务都是不可见的
    T1 会话连接 T2 会话连接
    t1 BEGIN;
    SELECT txid_current();
    INSERT INTO tbl_mvcc(id,ival) VALUES (7,7);
    SELECT xmin, xmax, cmin, cmax, id, ival FROM tbl_mvcc WHERE id = 7;
    t2 BEGIN;
    SELECT txid_current();
    SELECT xmin, xmax, cmin, cmax, id, ival FROM tbl_mvcc WHERE id = 7;
    t3 ROLLBACK;

    回滚的事务或未提交的事务创建的行对于任何其他事务都是不可见的。T1的事务(事务ID:3833)插入一条记录,查询隐含列xmin值为3833(即事务ID)。新开另一个连接T2开启一个新事务(事务ID:3834)查询表tbl_mvcc中id=7的记录,返回0条记录。第一个事务对于第二个事务不可见。

    image-20200609221331952

    事务无论提交还是回滚,事务ID(xid)都会递增。对于Repeatable Read和Serializable隔离级别的事务,如果它的xid小于另外一个事务的xid,即元组的xmin小于另外一个事务的xmin,那么另外一个事务对这个事务是不可见的。

    T1 会话连接 T2 会话连接
    t1 BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    SELECT txid_current();
    SELECT xmin, xmax, cmin, cmax, id, ival FROM tbl_mvcc WHERE id = 7;
    t2 BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
    SELECT txid_current();
    INSERT INTO tbl_mvcc(id,ival) VALUES (7,7);
    SELECT xmin, xmax, cmin, cmax, id, ival FROM tbl_mvcc WHERE id = 7;
    COMMIT;
    t3 SELECT xmin, xmax, cmin, cmax, id, ival FROM tbl_mvcc WHERE id = 7;

    连接开启一个事务T1(xid=3835),另开启一个事务T2(xid=3836)并插入一条新记录。尽管T2事务已提交,事务T1仍然是未找到T2插入的数据。T1(xid=3835)< T2(xid=3836),因此id=7的值对于T1是不可见的。

    image-20200609222408730

    4.2.2 通过xmax决定事务可见性

    通过xmax值判断事务的更新操作和删除操作对其他事务的可见性

    • 如果没有设置xmax值,该行对其他事务总是可见的;
    • 如果它被设置为回滚事务的xid,该行对其他事务也是可见的;
    • 如果它被设置为一个正在运行,没有COMMIT和ROLLBACK的事务的xid,该行对其他事务是可见的;
    • 如果它被设置为一个已提交的事务的xid,该行对在这个己提交事务之后发起的所有事务都是不可见的。

    4.3 插件pageinspect查看数据页内容

    在PostgreSQL中,可以使用pageinspect这个外部扩展来观察数据库页面的内容。pageinspect提供了一些函数可以得到数据库的文件系统中页面的详细内容。

    4.3.1 安装创建

    需要superuser权限

    psql devdb
    CREATE EXTENSION pageinspect ;
    -- 查看
    dx+ pageinspect
                    Objects in extension "pageinspect"
                            Object description                         
    -------------------------------------------------------------------
     function brin_metapage_info(bytea)
     function brin_page_items(bytea,regclass)
     function brin_page_type(bytea)
     function brin_revmap_data(bytea)
     function bt_metap(text)
     function bt_page_items(bytea)
     function bt_page_items(text,integer)
     function bt_page_stats(text,integer)
     function fsm_page_contents(bytea)
     function get_raw_page(text,integer)
     function get_raw_page(text,text,integer)
     function gin_leafpage_items(bytea)
     function gin_metapage_info(bytea)
     function gin_page_opaque_info(bytea)
     function hash_bitmap_info(regclass,bigint)
     function hash_metapage_info(bytea)
     function hash_page_items(bytea)
     function hash_page_stats(bytea)
     function hash_page_type(bytea)
     function heap_page_item_attrs(bytea,regclass)
     function heap_page_item_attrs(bytea,regclass,boolean)
     function heap_page_items(bytea)
     function page_checksum(bytea,integer)
     function page_header(bytea)
     function tuple_data_split(oid,bytea,integer,integer,text)
     function tuple_data_split(oid,bytea,integer,integer,text,boolean)
    (26 rows)
    
    SELECT * FROM pg_extension ;
    

    get_raw_page(relname text, fork text, blkno int)和它的一个重载 get_raw_page(relname text,blkno int),用于读取 relation 中指定的块的值,其中 relname是 relation name , 参数 fork 可以有 main 、 vm 、 fsm 、 init 这几个值, fork默认值是 main, main 表示数据文件的主文件, vm 是可见性映射的块文件, fsm 为 free space map 的块文件 , init 是初始化的块 。 get_raw_page 以一个 bytea 值的形式返回 一个拷贝 。 heap_page_items 显示一个堆页面上所有的行指针 。 对那些使用中的行指针,元组头部和元组原始数据也会被显示 。 不管元组对于拷贝原始页面时的 MVCC 快照是否可见,它们都会被显示。一般使用 get_raw_page 函数获得堆页面映像作为参数传递给 heap_page_items

    创建视图跟踪MVCC如何控制并发时的多版本

    psql devdb
    -- 授权给Dev用户
    /*
    GRANT EXECUTE ON FUNCTION get_raw_page(text,text,integer) to dev;
    GRANT EXECUTE ON FUNCTION get_raw_page(text,integer) to dev;
    GRANT EXECUTE ON FUNCTION heap_page_items(bytea) to dev;
    */
    
    psql devdb 
    -- 创建视图
    DROP VIEW IF EXISTS v_pageinspect;
    CREATE VIEW v_pageinspect AS
    SELECT '(0,' || lp || ')' AS ctid,
          CASE lp_flags
              WHEN 0 THEN 'Unused'
              WHEN 1 THEN 'Normal'
              WHEN 2 THEN 'Redirect to ' || lp_off
              WHEN 3 THEN 'Dead'
          END,
          t_xmin::text::int8 AS xmin,
          t_xmax::text::int8 AS xmax,
          t_ctid
       FROM heap_page_items(get_raw_page('dev.tbl_mvcc',0))
       ORDER BY lp;
       
    
    SELECT * FROM v_pageinspect;
    select * from heap_page_items(get_raw_page('dev.tbl_mvcc',0)) order by lp_off desc;
    

    4.4 插件pg_repack解决表膨胀问题

    ​ 尽管PostgreSQL的MVCC读不阻塞写,写不阻塞读,实现了高性能和高吞吐量,但也有它不足的地方。通过观察数据块的内部结构,我们已经了解到在PostgreSQL中数据采用堆表保存,并且MVCC的旧版本和新版本存储在同一个地方,如果更新大量数据,将会导致数据表的膨胀。例如一张一万条数据的表,如果对它进行一次全量的更新,根据PostgreSQL的MVCC的实现方式,在数据文件中每条数据实际会有两个版本存在,一个版本是更新之前的旧版本,一个版本是更新之后的新版本,这两个版本并存必然导致磁盘的使用率是实际数据的一倍,对性能也略有影响。使用VACUUM命令或者autovacuum进程将旧版本的磁盘空间标记为可用,尽管VACUUM已经被实现得非常高效,但是没有办法把已经利用的磁盘空间释放给操作系统,VACUUM FULL命令可以回收可用的磁盘空间,但它会阻塞所有其他的操作。pg_repack是一个可以在线重建表和索引的扩展。它会在数据库中建立一个和需要清理的目标表一样的临时表,将目标表中的数据COPY到临时表,并在临时表上建立与目标表一样的索引,然后通过重命名的方式用临时表替换目标表。

    4.4.1 配置pg_repack

    # 1. 下载地址
    https://pgxn.org/dist/pg_repack/
    
    # 2. 安装软件
    rpm -Uvh postgresql-devel
    export PATH=$(which pg_config);$PATH
    cd pg_repack
    make
    make install
    
    # 3. 配置插件
    psql -c "CREATE EXTENSION pg_repack" -d your_database
    
    # 4. 移除插件
    psql -c "DROP EXTENSION pg_repack;" -d your_database
    OR
    psql -c "DROP SCHEMA repack;" -d your_database
    

    4.4.2 pg_repack语法

    pg_repack [OPTION]... [DBNAME]
    The following options can be specified in OPTIONS.
    
    Options:
    -a, --all	repack all databases
    -t, --table=TABLE
     	repack specific table only
    -I, --parent-table=TABLE
     	repack specific parent table and its inheritors
    -c, --schema=SCHEMA
     	repack tables in specific schema only
    -s, --tablespace=TBLSPC
     	move repacked tables to a new tablespace
    -S, --moveidx	move repacked indexes to TBLSPC too
    -o, --order-by=COLUMNS
     	order by columns instead of cluster keys
    -n, --no-order	do vacuum full instead of cluster
    -N, --dry-run	print what would have been repacked and exit
    -j, --jobs=NUM	Use this many parallel jobs for each table
    -i, --index=INDEX
     	move only the specified index
    -x, --only-indexes
     	move only indexes of the specified table
    -T, --wait-timeout=SECS
     	timeout to cancel other backends on conflict
    -D, --no-kill-backend
     	don't kill other backends when timed out
    -Z, --no-analyze
     	don't analyze at end
    -k, --no-superuser-check
     	skip superuser checks in client
    -C, --exclude-extension
     	don't repack tables which belong to specific extension
    Connection options:
    -d, --dbname=DBNAME
     	database to connect
    -h, --host=HOSTNAME
     	database server host or socket directory
    -p, --port=PORT
     	database server port
    -U, --username=USERNAME
     	user name to connect as
    -w, --no-password
     	never prompt for password
    -W, --password	force password prompt
    Generic options:
    -e, --echo	echo queries
    -E, --elevel=LEVEL
     	set output message level
    --help	show this help, then exit
    --version	output version information, then exit
    Reorg Options
    -a, --all
    Attempt to repack all the databases of the cluster. Databases where the pg_repack extension is not installed will be skipped.
    -t TABLE, --table=TABLE
    Reorganize the specified table(s) only. Multiple tables may be reorganized by writing multiple -t switches. By default, all eligible tables in the target databases are reorganized.
    -I TABLE, --parent-table=TABLE
    Reorganize both the specified table(s) and its inheritors. Multiple table hierarchies may be reorganized by writing multiple -I switches.
    -c, --schema
    Repack the tables in the specified schema(s) only. Multiple schemas may be repacked by writing multiple -c switches. May be used in conjunction with --tablespace to move tables to a different tablespace.
    -o COLUMNS [,...], --order-by=COLUMNS [,...]
    Perform an online CLUSTER ordered by the specified columns.
    -n, --no-order
    Perform an online VACUUM FULL. Since version 1.2 this is the default for non-clustered tables.
    -N, --dry-run
    List what would be repacked and exit.
    -j, --jobs
    Create the specified number of extra connections to PostgreSQL, and use these extra connections to parallelize the rebuild of indexes on each table. Parallel index builds are only supported for full-table repacks, not with --index or --only-indexes options. If your PostgreSQL server has extra cores and disk I/O available, this can be a useful way to speed up pg_repack.
    -s TBLSPC, --tablespace=TBLSPC
    Move the repacked tables to the specified tablespace: essentially an online version of ALTER TABLE ... SET TABLESPACE. The tables' indexes are left in the original tablespace unless --moveidx is specified too.
    -S, --moveidx
    Also move the indexes of the repacked tables to the tablespace specified by the --tablespace option.
    -i, --index
    Repack the specified index(es) only. Multiple indexes may be repacked by writing multiple -i switches. May be used in conjunction with --tablespace to move the index to a different tablespace.
    -x, --only-indexes
    Repack only the indexes of the specified table(s), which must be specified with the --table or --parent-table options.
    -T SECS, --wait-timeout=SECS
    pg_repack needs to take an exclusive lock at the end of the reorganization. This setting controls how many seconds pg_repack will wait to acquire this lock. If the lock cannot be taken after this duration and --no-kill-backend option is not specified, pg_repack will forcibly cancel the conflicting queries. If you are using PostgreSQL version 8.4 or newer, pg_repack will fall back to using pg_terminate_backend() to disconnect any remaining backends after twice this timeout has passed. The default is 60 seconds.
    -D, --no-kill-backend
    Skip to repack table if the lock cannot be taken for duration specified --wait-timeout, instead of cancelling conflicting queries. The default is false.
    -Z, --no-analyze
    Disable ANALYZE after a full-table reorganization. If not specified, run ANALYZE after the reorganization.
    -k, --no-superuser-check
    Skip the superuser checks in the client. This setting is useful for using pg_repack on platforms that support running it as non-superusers.
    -C, --exclude-extension
    Skip tables that belong to the specified extension(s). Some extensions may heavily depend on such tables at planning time etc.
    Connection Options
    Options to connect to servers. You cannot use --all and --dbname or --table or --parent-table together.
    
    -a, --all
    Reorganize all databases.
    -d DBNAME, --dbname=DBNAME
    Specifies the name of the database to be reorganized. If this is not specified and -a (or --all) is not used, the database name is read from the environment variable PGDATABASE. If that is not set, the user name specified for the connection is used.
    -h HOSTNAME, --host=HOSTNAME
    Specifies the host name of the machine on which the server is running. If the value begins with a slash, it is used as the directory for the Unix domain socket.
    -p PORT, --port=PORT
    Specifies the TCP port or local Unix domain socket file extension on which the server is listening for connections.
    -U USERNAME, --username=USERNAME
    User name to connect as.
    -w, --no-password
    Never issue a password prompt. If the server requires password authentication and a password is not available by other means such as a .pgpass file, the connection attempt will fail. This option can be useful in batch jobs and scripts where no user is present to enter a password.
    -W, --password
    Force the program to prompt for a password before connecting to a database.
    
    This option is never essential, since the program will automatically prompt for a password if the server demands password authentication. However, pg_repack will waste a connection attempt finding out that the server wants a password. In some cases it is worth typing -W to avoid the extra connection attempt.
    
    Generic Options
    -e, --echo
    Echo commands sent to server.
    -E LEVEL, --elevel=LEVEL
    Choose the output message level from DEBUG, INFO, NOTICE, WARNING, ERROR, LOG, FATAL, and PANIC. The default is INFO.
    --help
    Show usage of the program.
    --version
    Show the version number of the program.
    

    4.4.3 示例

    # 1. 使用 pg_repack 对 tbl_mvcc 表进行重建
    pg_repack -t tbl_mvcc -j 2 -D -k -h progs -U postgres -d devdb
    
  • 相关阅读:
    【职业规划】一位资深程序员大牛给予Java初学者的学习路线建议
    一个断点调试的小技巧
    无穷分数
    Spring事务异常回滚,捕获异常不抛出就不会回滚
    理解Servlet和Servlet容器、Web服务器等概念
    图解红黑树及Java进行红黑二叉树遍历的方法
    Majority Element
    Factorial Trailing Zeroes
    Valid Parentheses
    House Robber
  • 原文地址:https://www.cnblogs.com/binliubiao/p/13176306.html
Copyright © 2020-2023  润新知