在linux shell脚本中使用Postgres事务

时间:2012-08-24 20:06:40

标签: linux postgresql shell

我正在开发一个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

有没有办法实现这个目标?如果没有,有哪些替代方案?

谢谢!

1 个答案:

答案 0 :(得分:2)

您的脚本有两个主要问题。第一个问题是实际的:事务是特定会话的一部分,因此您的第一个psql命令只是启动事务然后退出,没有实际效果:事务在命令完成时结束,以及后来的命令不要分享。第二个问题是概念性的:事务Y在事务X提交之前不会看到事务X中所做的更改,但是一旦事务X被提交,事务Y就会立即看到它们,即使事务Y仍然在 - 进展。这意味着,即使您的脚本成功地将整个转储包装在单个事务中,这也没有任何区别,因为您的转储仍然会看到从一个查询到下一个查询的结果不一致。 (也就是说:在事务中包含一系列SELECT是没有意义的。只有当事务包含一个或多个DML语句UPDATEINSERT或{时,事务才有意义。 {1}}峰)

但是,因为你并不真的需要你的shell脚本来遍历你的表列表;相反,你可以通过传递多个DELETE标志,一次性给出pg_dump所有表名:

-t

according to the documentationpg_dump -U postgres -h $IP_ADDRESS -p 5432 \ -t table1 -t table2 -t table3 -a --inserts MYDB >> out.sql “即使同时使用数据库也会进行一致的备份”,因此即使确实有所帮助,您也不必担心设置事务。

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