繁体   English   中英

将PSQL COPY表转换为CSV-生产数据库上的数据一致性

[英]PSQL COPY tables to CSV - Data consistency on production database

我正在使用以下shell脚本对数据库进行转储以分离CSV文件:

PGENGINE=$PGHOME/bin
PGPASSWORD=$1 $PGENGINE/psql -p $2 -h $3 -U $4 -Atc "select tablename from pg_tables where schemaname='public'" $5 |\
while read TBL; do
    echo "Exporting table "$TBL
    PGPASSWORD=$1 $PGENGINE/psql -p $2 -h $3 -U $4 -c "COPY public.$TBL TO STDOUT WITH CSV HEADER DELIMITER '"$SEPARATEUR_CSV"'" $5 > /$ROOT_PATH/$6/$TBL.csv
    echo -e $TBL ": Export done\n"
done

这在我的测试数据库上可以正常工作,但是我担心在生产数据库上运行它会发生什么。

我看到许多主题都在说pg_dump获得了数据锁定,但是我不了解psql COPY,包括我在所有表上循环的事实。 我需要确保,如果用户更新了我的一张表,则COPY命令仍将获取正确的数据和正确的FK。

我的问题:

  1. 您认为这是正确的方法吗? 存储过程对数据一致性是否更安全?

  2. 实现这一目标的最有效方法是什么? (由于该生产数据库非常大-有些表超过3000万行)。

通过在REPEATABLE READ隔离模式下启动事务并在读取所有内容时结束该事务,可以实现实时数据库中各表之间的一致读取。 必须对脚本进行转换,以便只有一个psql调用,如下所示:

psql [connection arguments] << EOF
BEGIN;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
\copy table1 TO file1.csv
\copy table2 TO file2.csv
\copy table3 TO file3.csv
COMMIT;

EOF

注意\\copy而不是COPY ,这是因为将所有分组归入同一psql调用。 psql本身会将每个\\copy的数据路由到每个客户端输出文件。

这也是一个两步工作流:首先生成上面的脚本(例如通过在psql -c 'select tablename....'的结果上循环bash或任何其他方法),然后执行该脚本。

为什么不能简化为一步?

循环无法在psql脚本中实现,因为psql没有循环,除非使用\\gexec ,但在这里不适用,因为\\copy是元命令,并且\\gexec仅处理SQL命令。

除非更改问题的上下文,否则也无法在plpgsql中实现该循环,因为COPY TO STDOUT每个输出都不会路由到相应的每表客户端文件。 当所有内容合并为一个流时,它将返回给客户端。 如果使用SQL命令COPY TO file它可以工作,但是您需要成为超级用户,并且文件最终存储在服务器上,而不是在客户端上。

我最终得到了这个解决方案:

PGENGINE=$PGHOME/bin
    CHEMIN_SCRIPT_TRANSACTION=/$ROOT_PATH/plc/proc/tmp/dump_transaction.sql
    DOSSIER_DUMP_FICHIERS=/$ROOT_PATH/dump/dump_$6/dump_fichiers

    echo "BEGIN; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;" > $CHEMIN_SCRIPT_TRANSACTION

    PGPASSWORD=$1 $PGENGINE/psql -p $2 -h $3 -U $4 -Atc "select tablename from pg_tables where schemaname='public'" $5 |\
    while read TBL; do
        echo "\copy $TBL TO $DOSSIER_DUMP_FICHIERS/$TBL.csv WITH CSV HEADER DELIMITER ';';" >> $CHEMIN_SCRIPT_TRANSACTION
        echo "\echo " >> $CHEMIN_SCRIPT_TRANSACTION
    done
    echo "COMMIT;" >> $CHEMIN_SCRIPT_TRANSACTION

    PGPASSWORD=$1 $PGENGINE/psql -p $2 -h $3 -U $4 -d $5 -f $CHEMIN_SCRIPT_TRANSACTION

我正在其他文件中创建脚本,然后使用psql -f播放此脚本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM