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



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

  1. 如果您想完全恢复到备份状态,请将其转储到数据库中
  2. 将其转储到本地以"查看",或在开发环境中使用生产数据
  3. 将数据库的特定行设置为以前的状态(例如,恢复意外删除的行)

我发现自己在后一点上非常挣扎,所以我想分享我是如何做到的。

如何在Postgres Heroku上恢复以前备份的特定数据

摘要/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也可以(通过示例阅读本文)
  • 在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上发现了这个问题:从本地现有类型指定dblink列定义列表,这对我有很大帮助(谢谢benterm)。

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

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

我的目标仍然是1线。在经历了一些小痛苦之后(不是SQL专家),以下是Gist: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

希望我是清白的!请询问更多详细信息,否则

最新更新