如何从Postgres Heroku上的先前备份恢复特定数据? (例如,意外删除的行)

时间:2014-09-09 09:43:22

标签: postgresql heroku ngrok

情况如下:Heroku& Postgres,您可以自动生成备份转储文件。 但你能用它做什么?

  1. 如果您想完全返回备份状态,请将其转储到您的数据库
  2. 将其转储到本地“看看”,或在开发环境中使用生产数据
  3. 以先前状态设置数据库的特定行(例如,恢复意外删除的行)
  4. 我发现自己非常挣扎关于后一点,我想分享我是如何做到的。

    如何从Postgres Heroku上的先前备份恢复特定数据?

1 个答案:

答案 0 :(得分:8)

摘要/ TL; DR

通过3个步骤,您将能够非常简单地执行:

INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name -- backup_db being remote

首先在本地安装备份,第二次安装SQL脚本,第三次使用 ngrok 将本地主机打开到外部世界。

我们走吧?

1。在Heroku下载转储文件并将其转储到某处:

  • 如果您有一些可用的服务器,则可以在远程数据库上执行此操作。但是如果像我这样你不想在Heroku或其他地方配置另一个生产数据库,那么本地就完全可以了。
  • 我喜欢使用PGAdmin(可在Linux,Mac和Windows上使用),但使用命令行和psql也可以(通过示例阅读此post
  • 在PGAdmin中,您需要Create a database。然后右键单击它并使用restore功能。选择您的转储文件,点击Restore即可完成设置:您的备份数据在本地可用!干得好!

2。从远程数据库访问它

我想做以下事情:

SELECT * FROM backup_db.table_name
-- So I could then do
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name

我会全力以赴。超级简单吧?很明显?这必须已经完成了数百次。好吧,不!

在Postgres 9.1+中有一个名为db_link的实用程序,但由于以下语法适用,因此非常有限:

SELECT fname, lname FROM db_link('host=localhost dbname=backup-28-08', 'SELECT fname, lname FROM users') AS remote (varchar255 fname varchar255 lname)

每个列名称需要重复两次,包括其类型。非常沉重,我们远非简单的SELECT * FROM backup_db.table_name

所以这里的想法是使用information_schema表格内容,它描述每个表格及其列名,类型等。我在SO上发现了这个问题:Specify dblink column definition list from a local existing type帮助我很多(谢谢bentrm)。

但它的解决方案是一个两步流程,首先生成一个函数,然后查询它:

SELECT dblink_star_func('dbname=ben', 'public', 'test');
SELECT * FROM star_test() WHERE data = 'success';

我仍然瞄准一个班轮。经过一些小小的痛苦(不是SQL大师),这里是要点:https://gist.github.com/augnustin/d30973ea8b5bf0067841

我现在可以做到:

SELECT * FROM remote_db(NULL::users) -- (Still not 100% about why I need the NULL::)
-- And also
INSERT INTO users
SELECT * FROM remote_db(NULL::users)

太棒了吧?

3。远程访问localhost

如果您的远程数据库已经可以从互联网上获得(=有一个IP地址,域名例如。对于Heroku,它将如下所示:ec2-54-217-229-169.eu-west-1.compute.amazonaws.com:5672/df68cfpbufjd9p您可以跳过此步骤 。但是如果您使用本地数据库,则需要从外部世界使用它(以便Heroku数据库可以访问它)。

为此,我使用精彩ngrok

安装完成后,我只需要输入以下命令:

ngrok -proto=tcp 5432 #5432 being the default port for Postgresql. (Adapt if necessary)

Tunnel Status                 online                                                                                                                                                                
Version                       1.7/1.6                                                                                                                                                               
Forwarding                    tcp://ngrok.com:51727 -> 127.0.0.1:5432                                                                                                                               
Web Interface                 127.0.0.1:4040                                                                                                                                                        
# Conn                        0                                                                                                                                                                     
Avg Conn Time                 0.00ms    

而且你只需要将db_link(在要点中)插入host=ngrock.com port=51727,你好好去

4。更进一步

这有很多可能的改进。以下是我已经看到的一些内容:

  • 将脚本视为db_link功能
  • 的默认功能
  • 如果备份和生产中的数据库结构不同,则更加防错
  • 在数据库结果和备份结果之间建立比较工具(仅返回差异线)
  • 处理简单连接
  • 甚至还有一个应用程序级适配器(例如Rails中的ActiveRecord)可以允许操作后端对象而不是像现在这样的原始SQL

希望我很清楚!否则请询问更多细节