pgcompacttable + 使用pg_repack实现在线vacuum + 安装pg_repack +pg_repack可能跟流复制有冲突,建议使用pgcompacttable
1. Postgresql通过数据多版本实现mvcc,删除数据并不会真正删除数据,
而是修改标识,更新是通过删除+插入的方式进行,所以在频繁更新的系统,数据膨胀是个头疼的问题,如果不进行处理,数据膨胀倍数可能达到十几倍。
2. repack的原理
原理其实和vacuum full是类似的,都是新建一个文件,然后将老文件数据拷贝过来,然后进行文件切换,
它不阻塞读写的秘诀就是新建文件和拷贝的过程是在线做的,在没有完成拷贝之前,原来的文件还是可以读写的,只有在切表那一瞬间可能会有影响。
原理: 新建一个一模一样的影子表,然后拷贝原表的数据,最后rename替换原表。 安装pg_repack:
参考:使用pg_repack 回收表体积 - 云+社区 - 腾讯云 (tencent.com)
参考:使用pg_repack实现在线vacuum - 云+社区 - 腾讯云 (tencent.com)
3. pgcompacttable
#!/bin/bash ########################################################### #红牛数据维护pg_repack #20210908 changed to repack all database ########################################################### pg_repack_log=/home/pg_repack_log # 处理日期 backup_date=`date "+%Y-%m-%d"` #存放路径 log_file=pg_repack_${backup_date}.txt #开始时间 echo `date` >${pg_repack_log}/${log_file} for x in $(/usr/pgsql-10/bin/psql -U postgres -h 127.0.0.1 -d zuhu_512990 -c "select datname from pg_database where datname not in ('postgres','template0','template1'); " -A -t) do # if [ `/usr/pgsql-10/bin/psql -U postgres -h 127.0.0.1 -d ${x} -c "select count(1) from pg_extension where extname='pg_repack'; " -A -t` == 1 ] # then ##避免错误可直接写死路径 echo `date` >> ${pg_repack_log}/${log_file} /home/pgback/pgcompacttable/bin/pgcompacttable -U postgres -h 127.0.0.1 -d ${x} >> ${pg_repack_log}/${log_file} 2>&1 echo "pg_compatch ${x} success!!" >> ${pg_repack_log}/${log_file} echo `date` >> ${pg_repack_log}/${log_file} # else # create_ext=`psql -U postgres -h 127.0.0.1 -d ${d} << EOF # create extension pg_repack; #EOF` # fi done
4. pg_repack
#!/bin/bash ########################################################### #红牛数据维护pg_repack #可能存在处理偶数天的表完成时已跨天了,可能接着把奇数天的表也处理了。 #注意监控实际处理时长; ########################################################### pg_repack_log=/home/pg_repack_log # 处理日期 backup_date=`date "+%Y-%m-%d"` #存放路径 log_file=pg_repack_${backup_date}.txt #开始时间 echo `date` >${pg_repack_log}/${log_file} #取当前的具体日期,用来取模求余 ls_date=`date +%d` if [[ ${ls_date}%2 -eq 0 ]] then # 偶数天处理核心表清单; for x in $(psql -U postgres -h 127.0.0.1 -d
zuhu_512110
-c "select relname from pg_class where relname in ( 'kx_test_store','kx_test_actual' ); " -A -t) do ##避免错误可直接写死路径 echo `date` >> ${pg_repack_log}/${log_file} ` /usr/pgsql-10/bin/pg_repack -Upostgres -h127.0.0.1 -d tenant_1008446 -t ${x} >> ${pg_repack_log}/${log_file} 2>&1 ` echo "pg_repack ${x} success!!" >> ${pg_repack_log}/${log_file} echo `date` >> ${pg_repack_log}/${log_file} done elif [[ ${ls_date}%2 -eq 1 ]]; then # 奇数天处理表清单; for x in $(psql -U postgres -h 127.0.0.1 -d tenant_1008446 -c "select relname from pg_class where relname NOT in ( 'do_test_store','do_test_actual' ) and relkind='r' and relpersistence='p' and relnamespace=2200; " -A -t) do ##2200 对应pg_namespace 的oid 为public ##避免错误可直接写死路径 echo `date` >> ${pg_repack_log}/${log_file} ` /usr/pgsql-10/bin/pg_repack -Upostgres -h127.0.0.1 -d zuhu_512110 -t ${x} >> ${pg_repack_log}/${log_file} 2>&1 ` echo "pg_repack ${x} success!!" >> ${pg_repack_log}/${log_file} echo `date` >> ${pg_repack_log}/${log_file} done else dd=`date` echo "***** ${dd} no shell need to run.*****" >> ${pg_repack_log}/${log_file} fi
用一个例子来演示会更加清晰