0

我正在开发一个 shell 脚本,它遍历一系列 Postgres 数据库表名并转储表数据。例如:

# dump data

psql -h $SRC_IP_ADDRESS -p 5432 -U postgres -c "BEGIN;" AWARE

do
 :
 pg_dump -U postgres -h $IP_ADDRESS -p 5432 -t $i -a --inserts MYDB >> \
 out.sql
done

psql -h $IP_ADDRESS -p 5432 -U postgres -c "COMMIT;" MYDB

但是,我担心对数据库的并发访问。由于 Postgres 没有数据库锁,我尝试在循环周围包裹一个 BEGIN 和 COMMIT(使用 psql,如上所示)。这导致来自 psql 命令的错误消息,说:

WARNING:  there is no transaction in progress

有什么办法可以做到这一点?如果没有,有什么替代方案?

谢谢!

4

1 回答 1

2

您的脚本有两个主要问题。第一个问题是实际的:事务是特定会话的一部分,所以你的第一个psql命令,它只是启动一个事务然后退出,没有实际效果:事务在命令完成时结束,后面的命令不共享它。第二个问题是概念上的:在事务 X 提交之前,事务 X 中所做的更改不会被事务 Y 看到,但是一旦事务 X 提交,它们就会立即被事务 Y 看到,即使事务 Y 仍然在-进步。这意味着,即使您的脚本确实成功地将整个转储包装在一个事务中,这也不会产生任何影响,因为您的转储仍然可以看到从一个查询到下一个查询的不一致结果。(即:包装一系列的没有意义SELECTs 在事务中。UPDATE一个事务只有在它包含一个或多个 DML 语句( s 或INSERTs 或s)时才有意义DELETE。)

但是,由于您实际上并不需要您的 shell 脚本来遍历您的表列表;相反,您可以通过传递多个标志pg_dump一次给出所有表名:-t

pg_dump -U postgres -h $IP_ADDRESS -p 5432 \
    -t table1 -t table2 -t table3 -a --inserts MYDB >> out.sql

并且根据文档pg_dump“即使数据库正在同时使用,也会进行一致的备份”,因此即使有帮助,您也不必担心设置事务。

(顺便说一下,该-t标志还支持 glob 表示法;例如,-t table*将匹配名称以 . 开头的所有表table。)

于 2012-08-24T20:19:08.503 回答