os: ubuntu 16.04
db: postgresql 9.6.8
pg_repack: 1.4.4
postgresql 的 vacuum full 需要 access exclusive lock,获得这个锁后,针对该表的所有操作均无法执行,包括 select
pg_repack is a fork of the pg_reorg project, which has proven hugely successful. Unfortunately new feature development on pg_reorg has slowed or stopped since late 2011.
版本
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.5 LTS
Release: 16.04
Codename: xenial
$ psql
psql (9.6.8)
Type "help" for help.
postgres=# select version();
version
----------------------------------------------------------------------------------------------------------------------------------------------
PostgreSQL 9.6.8 on x86_64-pc-linux-gnu (Ubuntu 9.6.8-1.pgdg16.04+1), compiled by gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609, 64-bit
(1 row)
postgres=#
下载安装
在 https://github.com/reorg/pg_repack/releases
或者 https://pgxn.org/dist/pg_repack
都可以下载
$ wget https://github.com/reorg/pg_repack/archive/ver_1.4.4.zip
或者
$ wget http://api.pgxn.org/dist/pg_repack/1.4.4/pg_repack-1.4.4.zip
安装依赖包
# apt install cmake libssl-dev
$ unzip pg_repack-ver_1.4.4.zip
$ ls -l
drwxrwxr-x 8 postgres postgres 4096 Oct 18 19:30 pg_repack-ver_1.4.4
-rw-r--r-- 1 postgres postgres 124311 Dec 14 2018 pg_repack-ver_1.4.4.zip
$ cd pg_repack-ver_1.4.4
$ make
make[1]: Entering directory '/var/lib/postgresql/pg_repack-ver_1.4.4/bin'
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -pie -fno-omit-frame-pointer pg_repack.o pgut/pgut.o pgut/pgut-fe.o -L/usr/lib/x86_64-linux-gnu -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -L/usr/lib/x86_64-linux-gnu/mit-krb5 -Wl,--as-needed -L/usr/lib/x86_64-linux-gnu -lpq -L/usr/lib/postgresql/9.6/lib -lpgcommon -lpgport -lssl -lcrypto -lz -lrt -lcrypt -ldl -lm -o pg_repack
make[1]: Leaving directory '/var/lib/postgresql/pg_repack-ver_1.4.4/bin'
make[1]: Entering directory '/var/lib/postgresql/pg_repack-ver_1.4.4/lib'
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -pie -fno-omit-frame-pointer -fPIC -DREPACK_VERSION=1.4.4 -I. -I./ -I/usr/include/postgresql/9.6/server -I/usr/include/postgresql/internal -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2 -I/usr/include/mit-krb5 -c -o repack.o repack.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -pie -fno-omit-frame-pointer -fPIC -DREPACK_VERSION=1.4.4 -I. -I./ -I/usr/include/postgresql/9.6/server -I/usr/include/postgresql/internal -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2 -I/usr/include/mit-krb5 -c -o pgut/pgut-spi.o pgut/pgut-spi.c
( echo '{ global:'; mawk '/^[^#]/ {printf "%s;\n",$1}' exports.txt; echo ' local: *; };' ) >exports.list
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -pie -fno-omit-frame-pointer -fPIC -shared -Wl,--version-script=exports.list -o pg_repack.so repack.o pgut/pgut-spi.o -L/usr/lib/x86_64-linux-gnu -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -L/usr/lib/x86_64-linux-gnu/mit-krb5 -Wl,--as-needed
sed 's,REPACK_VERSION,1.4.4,g' pg_repack.sql.in > pg_repack--1.4.4.sql;
sed 's,REPACK_VERSION,1.4.4,g' pg_repack.control.in > pg_repack.control
make[1]: Leaving directory '/var/lib/postgresql/pg_repack-ver_1.4.4/lib'
make[1]: Entering directory '/var/lib/postgresql/pg_repack-ver_1.4.4/regress'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/var/lib/postgresql/pg_repack-ver_1.4.4/regress'
使用apt安装就需要在root下 make install(或者使用sudo),主要是权限的问题。
pg_repack 依赖 postgresql-server-dev-X.Y
make时出错,一般都是缺少依赖包导致,按照错误提示按照即可。
$ sudo make install
make[1]: Entering directory '/var/lib/postgresql/pg_repack-ver_1.4.4/bin'
/bin/mkdir -p '/usr/lib/postgresql/9.6/bin'
/usr/bin/install -c pg_repack '/usr/lib/postgresql/9.6/bin'
make[1]: Leaving directory '/var/lib/postgresql/pg_repack-ver_1.4.4/bin'
make[1]: Entering directory '/var/lib/postgresql/pg_repack-ver_1.4.4/lib'
/bin/mkdir -p '/usr/lib/postgresql/9.6/lib'
/bin/mkdir -p '/usr/share/postgresql/9.6/extension'
/bin/mkdir -p '/usr/share/postgresql/9.6/extension'
/usr/bin/install -c -m 755 pg_repack.so '/usr/lib/postgresql/9.6/lib/pg_repack.so'
/usr/bin/install -c -m 644 .//pg_repack.control '/usr/share/postgresql/9.6/extension/'
/usr/bin/install -c -m 644 pg_repack--1.4.4.sql pg_repack.control '/usr/share/postgresql/9.6/extension/'
make[1]: Leaving directory '/var/lib/postgresql/pg_repack-ver_1.4.4/lib'
make[1]: Entering directory '/var/lib/postgresql/pg_repack-ver_1.4.4/regress'
make[1]: Nothing to be done for 'install'.
make[1]: Leaving directory '/var/lib/postgresql/pg_repack-ver_1.4.4/regress'
测试
pg_repack 是以 extension 的方式工作的。
peiybdb=# select * from pg_available_extensions where name like '%repack%' order by name;
name | default_version | installed_version | comment
-----------+-----------------+-------------------+--------------------------------------------------------------
pg_repack | 1.4.4 | | Reorganize tables in PostgreSQL databases with minimal locks
(1 row)
peiybdb=# create extension pg_repack;
CREATE EXTENSION
peiybdb=# \dn
List of schemas
Name | Owner
--------+----------
public | postgres
repack | postgres
(2 rows)
$ which pg_repack
/usr/lib/postgresql/9.6/bin/pg_repack
online vacuum full (include table indexes)
peiybdb=# \d+ tmp_t0
Table "public.tmp_t0"
Column | Type | Modifiers | Storage | Stats target | Description
--------+--------+-----------+---------+--------------+-------------
c0 | bigint | | plain | |
c1 | bigint | | plain | |
Indexes:
"idx_tmp_t0_c1" btree (c1)
$ pg_repack --no-order --table tmp_t0 peiybdb
WARNING: relation "public.tmp_t0" must have a primary key or not-null unique keys
添加主键
peiybdb=# drop index idx_tmp_t0_c1;
peiybdb=# ALTER TABLE public.tmp_t0 ADD CONSTRAINT tmp_t0_pk PRIMARY KEY (c1) ;
peiybdb=# with tmp_0 as (
select pc.oid as reloid,
pn.nspname,
pc.relname,
pn.nspname||'.'||pc.relname as schema_relname,
pc.relkind
from pg_class pc,
pg_namespace pn
where 1=1
and pc.relnamespace=pn.oid
)
select t0.reloid as tableoid,
pt.schemaname||'.'||pt.tablename as schema_tablename,
pg_relation_filepath(pt.schemaname||'.'||pt.tablename),
pg_table_size(pt.schemaname||'.'||pt.tablename),
pg_relation_size(pt.schemaname||'.'||pt.tablename),
pg_total_relation_size(pt.schemaname||'.'||pt.tablename),
t1.reloid as indexoid,
pi.schemaname||'.'||pi.indexname,
pg_relation_filepath(pi.schemaname||'.'||pi.indexname),
pg_relation_size(pi.schemaname||'.'||pi.indexname),
pg_indexes_size(pi.schemaname||'.'||pi.tablename)
from pg_tables pt
left outer join pg_indexes pi
on pt.schemaname||'.'||pt.tablename = pi.schemaname||'.'||pi.tablename
left outer join tmp_0 t0
on pt.schemaname||'.'||pt.tablename = t0.schema_relname
left outer join tmp_0 t1
on pi.schemaname||'.'||pi.indexname = t1.schema_relname
where 1=1
and pt.schemaname='public'
and pt.tablename='tmp_t0'
;
tableoid | schema_tablename | pg_relation_filepath | pg_table_size | pg_relation_size | pg_total_relation_size | indexoid | ?column? | pg_relation_filepath | pg_relation_size | pg_indexes_size
----------+------------------+----------------------+---------------+------------------+------------------------+----------+------------------+----------------------+------------------+-----------------
1447603 | public.tmp_t0 | base/1406609/1447745 | 44318720 | 44285952 | 66805760 | 1447752 | public.tmp_t0_pk | base/1406609/1447752 | 22487040 | 22487040
(1 row)
再次执行
$ pg_repack --no-order --table tmp_t0 -d peiybdb
tableoid | schema_tablename | pg_relation_filepath | pg_table_size | pg_relation_size | pg_total_relation_size | indexoid | ?column? | pg_relation_filepath | pg_relation_size | pg_indexes_size
----------+------------------+----------------------+---------------+------------------+------------------------+----------+------------------+----------------------+------------------+-----------------
1447603 | public.tmp_t0 | base/1406609/1447769 | 44318720 | 44285952 | 66805760 | 1447752 | public.tmp_t0_pk | base/1406609/1447772 | 22487040 | 22487040
(1 row)
可以看到,不管是 tmp_t0 (oid=1447603) 还是 tmp_t0_pk (oid=1447752),对应的 oid 都没有发生变化,但是在磁盘上的文件发生了变化。
online repack database
$ pg_repack --wait-timeout 3600 --jobs 10 --no-order -d peiybdb
online repack schema
$ pg_repack --wait-timeout 3600 --jobs 10 --no-order --schema=public -d peiybdb
online repack table and indexes
$ pg_repack --wait-timeout 3600 --no-order --table public.tmp_t0 -d peiybdb
online repack only all index
$ pg_repack --only-indexes --table public.tmp_t0 -d peiybdb
online repack only some index
$ pg_repack --index public.tmp_t0_pk -d peiybdb
参考:
http://reorg.github.com/pg_repack
https://pgxn.org/dist/pg_repack
https://github.com/reorg/pg_repack