【问题标题】:How to synchronize a postgresql database with data from mysql database?如何将 postgresql 数据库与 mysql 数据库中的数据同步?
【发布时间】:2011-01-12 12:34:28
【问题描述】:

我在位置 A (LA-MySQL) 有一个使用 MySQL 数据库的应用程序;位置 B 的另一个应用程序 (LB-PSQL) 使用 PostgreSQL 数据库。 (如果重要的话,我的位置是指物理上遥远的地方和不同的网络)

我需要在 LB-PSQL 更新一个表以与 LA-MySQL 同步,但我不知道这方面的最佳实践是什么。

另外,我需要在 LB-PSQL 更新的表不一定具有与 LA-MySQL 相同的结构。 (但我认为这不是问题,因为我需要在 LB-PSQL 上更新的字段能够容纳来自 LA-MySQL 字段的数据)

鉴于这些数据,哪些是做这类事情的最佳实践、常用方法或参考?

提前感谢您的任何反馈!

【问题讨论】:

  • 您需要同步(慢,在主提交时在副本上看到更改)还是异步(快速,但在延迟一段时间后可以看到副本上的更改)。如果是异步的,那么您可以忍受什么样的延迟:几秒钟、几小时、一天?
  • @Tometzky,它可以完美地成为一个异步任务。至于延迟,我可以忍受一天/一周之间的一些事情。

标签: php mysql database postgresql synchronization


【解决方案1】:

如果两台服务器位于不同的网络中,我看到的唯一机会是将数据从 MySQL 导出到平面文件中。

然后将文件(例如 FTP 或类似的东西)传输到 PostgreSQL 服务器并使用 COPY 将其导入那里

我建议将平面文件导入临时表。从那里您可以使用 SQL 将数据移动到适当的目标表。这将使您有机会进行数据转换或对现有行进行更新。

如果该转换更复杂,您可能需要考虑使用 ETL 工具(例如 Kettle)在目标服务器上进行迁移。

【讨论】:

  • 谢谢,但我期待某种“自动化流程”解决方案,通过 FTP 导出、传输和导入并不理想。
  • 如果没有预先投入,就不会有 100% 自动化的流程。您必须做点什么。您可以查看 ETL 工具(可能是 Pentaho),因为它们是为此类任务设计的,但仍然需要做一些开发工作来创建 ETL 流程。
【解决方案2】:

只需在 LA 上创建一个可以执行以下操作的脚本(bash 示例):

TMPFILE=`mktemp` || (echo "mktemp failed" 1>&2; exit 1)
pg_dump --column-inserts --data-only --no-password \
  --host="LB_hostname" --username="username" \
  --table="tablename" "databasename" \
  awk '/^INSERT/ {i=1} {if(i) print} # ignore everything to first INSERT' \
  > "$TMPFILE" \
  || (echo "pg_dump failed" 1>&2; exit 1)
(echo "begin; truncate tablename;"; cat "$TMPFILE"; echo 'commit;' ) \
  | mysql "databasename" < "$TMPFILE" \
  || (echo "mysql failed" 1>&2; exit 1) \
rm "$TMPFILE"

并将其设置为例如每天在 cron 中运行一次。你需要一个 '.pgpass' 作为 postgresql 密码和 mysql 选项文件作为 mysql 密码。

对于不到一百万行,这应该足够快。

【讨论】:

  • 你能解释一下awk吗?
  • 有一条评论 - “忽略一切以首先插入”。 pg_dump 生成一些与其他数据库不兼容的配置行 - 此 awk 忽略所有内容,直到出现以“INSERT”开头的行。
  • 我已经阅读了评论;)我更感兴趣的是为什么(“pg_dump 为 [...] 生成一些行”)。
  • @Tometzky:这不是做错了吗?据我了解,MySQL 应该是 source 而 Postgres 应该是 target。据我所知,您的解决方案使用 Postgres 作为来源。
  • @a_horse_with_no_name: eee... 以正确的方向实现这一点,留给读者作为练习;-)
【解决方案3】:

不是一个交钥匙解决方案,但这是一些使用触发器帮助完成此任务的代码。为简洁起见,以下假设没有删除或更新。需要PG>=9.1

1) 准备 2 个新表。 mytable_a 和 mytable_b。与要复制的源表具有相同的列:

CREATE TABLE  mytable_a AS TABLE mytable WITH NO DATA;
CREATE TABLE  mytable_b AS TABLE mytable WITH NO DATA;

-- trigger function which copies data from mytable to mytable_a on each insert
CREATE OR REPLACE FUNCTION data_copy_a() RETURNS trigger AS $data_copy_a$
    BEGIN
    INSERT INTO mytable_a SELECT NEW.*;
        RETURN NEW;
    END;
$data_copy_a$ LANGUAGE plpgsql;

-- start trigger
CREATE TRIGGER data_copy_a AFTER INSERT ON mytable FOR EACH ROW EXECUTE PROCEDURE data_copy_a();

那么当你需要导出时:

-- move data from mytable_a -> mytable_b without stopping trigger
WITH d_rows AS (DELETE FROM mytable_a RETURNING * )  INSERT INTO mytable_b SELECT * FROM d_rows; 

-- export data from mytable_b -> file
\copy mytable_b to '/tmp/data.csv' WITH DELIMITER ',' csv; 

-- empty table
TRUNCATE mytable_b;

然后你可以将data.csv导入mysql。

【讨论】:

    猜你喜欢
    • 2019-01-30
    • 1970-01-01
    • 2014-08-22
    • 2013-11-12
    • 1970-01-01
    • 1970-01-01
    • 2017-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多