在 Linux (Kubuntu) 上从 MySQL 迁移到 PostgreSQL

Posted

技术标签:

【中文标题】在 Linux (Kubuntu) 上从 MySQL 迁移到 PostgreSQL【英文标题】:Migrate from MySQL to PostgreSQL on Linux (Kubuntu) 【发布时间】:2011-02-19 08:02:34 【问题描述】:

很久以前在一个很远很远的系统上......

尝试将数据库从 mysql 迁移到 PostgreSQL。我读过的所有文档都非常详细地介绍了如何迁移结构。我发现很少有关于迁移数据的文档。该架构有 13 个表(已成功迁移)和 9 GB 数据。

MySQL 版本:5.1.x PostgreSQL 版本:8.4.x

我想使用 R 编程语言使用 SQL 选择语句分析数据; PostgreSQL 有 PL/R,但 MySQL 什么都没有(据我所知)。

新希望

创建数据库位置(/var 空间不足;也不喜欢到处都有 PostgreSQL 版本号——升级会破坏脚本!):

    sudo mkdir -p /home/postgres/main sudo cp -Rp /var/lib/postgresql/8.4/main /home/postgres sudo chown -R postgres.postgres /home/postgres sudo chmod -R 700 /home/postgres sudo usermod -d /home/postgres/ postgres

到这里一切顺利。接下来,重启服务器并使用这些installation instructions配置数据库:

    sudo apt-get install postgresql pgadmin3 sudo /etc/init.d/postgresql-8.4 stop sudo vi /etc/postgresql/8.4/main/postgresql.confdata_directory 更改为/home/postgres/main sudo /etc/init.d/postgresql-8.4 start sudo -u postgres psql postgres \password postgres sudo -u postgres createdb climate pgadmin3

使用pgadmin3 配置数据库并创建架构。

这一集在称为bash 的远程shell 中继续,两个数据库都在运行,并安装了一组带有相当不寻常徽标的工具:SQL Fairy。

    perl Makefile.PL sudo make install sudo apt-get install perl-doc(奇怪的是不叫perldocperldoc SQL::Translator::Manual

提取 PostgreSQL 友好的 DDL 和所有 MySQL 数据:

    sqlt -f DBI --dsn dbi:mysql:climate --db-user user --db-password password -t PostgreSQL > climate-pg-ddl.sql 编辑climate-pg-ddl.sql并将标识符转换为小写,并插入模式引用(使用VIM): :%s/"\([A-Z_]*\)"/\L\1/g :%s/ TABLE / TABLE climate./g :%s/ on / on climate./g mysqldump --skip-add-locks --complete-insert --no-create-db --no-create-info --quick --result-file="climate-my.sql" --databases climate --skip-comments -u root -p

将 MySQL 中的表和列简单地重命名为小写可能是值得的:

    select concat( 'RENAME TABLE climate.', TABLE_NAME, ' to climate.', lower(TABLE_NAME), ';' ) from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='climate'; 执行上一步中的命令。 可能有一种方法可以对列执行相同的操作;我手动更改了它们,因为它比弄清楚如何编写查询要快。

数据库反击

在 PostgreSQL 中重新创建结构如下:

    pgadmin3(切换到它) 点击执行任意 SQL 查询图标 打开climate-pg-ddl.sql 搜索 TABLE " 替换为 TABLE climate."(插入架构名称 climate) 搜索 on " 替换为 on climate."(插入架构名称 climate) 按F5执行

这会导致:

Query returned successfully with no result in 122 ms.

绝地的回复

此时我被难住了。

我该从哪里开始(步骤是什么)将climate-my.sql 转换为climate-pg.sql 以便它们可以针对PostgreSQL 执行? 如何确保索引被正确复制(以保持引用完整性;我目前没有任何限制来简化转换)? 如何确保在 PostgreSQL 中添加新行将从插入的最后一行的索引开始枚举(并且不与序列中的现有主键冲突)? 在将数据从 MySQL 转换为 PostgreSQL 插入时,如何确保架构名称通过?

资源

需要相当多的信息才能做到这一点:

https://help.ubuntu.com/community/PostgreSQL http://articles.sitepoint.com/article/site-mysql-postgresql-1 http://wiki.postgresql.org/wiki/Converting_from_other_Databases_to_PostgreSQL#MySQL http://pgfoundry.org/frs/shownotes.php?release_id=810 http://sqlfairy.sourceforge.net/

谢谢!

【问题讨论】:

+1 让@标题大笑。 我相信您有充分的理由迁移到 postgresql,但请注意,MySQL 和 R 之间缺少数据库接口不一定是其中之一:查看cran.r-project.org/web/packages/RMySQL(由Kubuntu 上的 r-cran-rmysql 包)。 pl/r 非常非常好。一般来说,PL 语言几乎值得单独转换。 【参考方案1】:

对于此类迁移,我通常会做两件事:

从 MySQL 中提取整个数据库定义并使其适应 PostgreSQL 语法。 检查数据库定义并对其进行转换,以利用 PostgreSQL 中 MySQL 中不存在的功能。

然后进行转换,并用您最熟悉的任何语言编写一个程序,以完成以下任务:

从 MySQL 数据库中读取数据。 对要存储在 PostgreSQL 数据库中的数据执行任何必要的转换。 将现在转换的数据保存在 PostgreSQL 数据库中。

为 PostgreSQL 重新设计表以利用其功能。

如果您只是使用sed 脚本将 SQL 转储从一种格式转换为另一种格式,那么您所做的就是将 MySQL 数据库放入 PostgreSQL 服务器中。您可以这样做,这样做仍然会有一些好处,但如果您要迁移,请完全迁移。

这需要花费更多的前期时间,但我还没有遇到不值得的情况。

【讨论】:

嗯,这是没有人可以回答的部分:只有你可以,在你重新设计了架构之后。我知道没有通用的方法可以有效地做到这一点。您使用 MySQL API 库读取您的 MySQL 表,如果您在 pgsql 中保持表完全相同,只需按原样编写它们。或者,如果您更改表/数据库结构以适应 pg 的功能,您可以在内存中对其进行转换,然后将其写入。但这是一个特定于数据的问题。如果您从 MySQL 转到 SQLite(例如,它的数据类型和功能较少),您会做同样的事情。 任何时候我将数据从一个 RDBMS 迁移到下一个(假设我都熟悉)我不会将转储转换为与目标兼容。事实上,我从不以这种方式进行转储,除了将其加载到空闲服务器中。更改数据库服务器是(正确的!)相当大的事情,尤其是对于具有复杂数据的应用程序。【参考方案2】:

将 mysqldump 文件转换为 PostgreSQL 友好格式

按如下方式转换数据(不要使用mysql2pgsql.perl):

    转义引号。

    sed "s/\\\'/\'\'/g" climate-my.sql | sed "s/\\\r/\r/g" | sed "s/\\\n/\n/g" > escaped-my.sql

    USE "climate"; 替换为搜索路径并注释 cmets:

    sed "s/USE \"climate\";/SET search_path TO climate;/g" escaped-my.sql | sed "s/^\/\*/--/" > climate-pg.sql

    连接到数据库。

    sudo su - postgrespsql climate

    设置编码(mysqldump忽略其编码参数),然后执行脚本。

    \encoding iso-8859-1\i climate-pg.sql

这一系列步骤可能不适用于具有多种混合类型的复杂数据库。但是,它适用于 integers、varchars 和 floats。

索引、主键和序列

由于mysqldump 在生成INSERT 语句时包含主键,它们将胜过表的自动序列。经检查,所有表的序列均保持为 1。

导入后设置顺序

使用ALTER SEQUENCE 命令将它们设置为所需的任何值。

架构前缀

无需在表前加上模式名称。使用:

SET search_path TO climate;

【讨论】:

【参考方案3】:

如果您已经转换了架构,那么迁移数据将是简单的部分:

从 PostgreSQL 中转储架构(您说您已将架构转换为 postgres,因此我们现在将其转储,因为我们将删除并重新创建目标数据库以对其进行清理):

pg_dump dbname > /tmp/dbname-schema.sql

将架构拆分为 2 部分 — /tmp/dbname-schema-1.sql 包含创建表语句,/tmp/dbname-schema-2.sql — 其余部分。 PostgreSQL需要在导入外键、触发器等之前导入数据,但是在导入表定义之后。

仅使用架构的 1 部分重新创建数据库:

删除数据库 dbname 创建数据库 dbname \i /tmp/dbname-schema-1.sql -- 现在我们有了没有数据、触发器、外键等的表。

导入数据:

( echo '开始交易'; mysqldump --skip-quote-names 数据库名 | grep ^插入; 回声“提交” ) | psql 数据库名称 -- 现在我们有了包含数据的表,但没有触发器、外键等。

在 MySQL 5.1.3 中添加了--skip-quote-names 选项,因此如果您有旧版本,则在/tmp/mysql 中临时安装更新的mysql(configure --prefix=/tmp/mysql && make install 应该这样做)并使用/tmp/mysql/bin/mysqldump

导入架构的其余部分:

psql 数据库名称 开始交易 \i /tmp/dbname-schema-2.sql 犯罪 ——我们完成了

【讨论】:

【参考方案4】:

查看etlalchemy。它允许您在 4 行 Python 中从 MySQL 迁移到 PostgreSQL,或在多个其他数据库之间迁移。你可以阅读更多关于它的信息here。

要安装:pip install etlalchemy

运行:

from etlalchemy import ETLAlchemySource, ETLAlchemyTarget
# Migrate from MySQL to PostgreSQL
src = ETLAlchemySource("mysql://user:passwd@hostname/dbname")
tgt = ETLAlchemyTarget("postgresql://user:passwd@hostname/dbname",
                          drop_database=True)
tgt.addSource(src)
tgt.migrate()

【讨论】:

以上是关于在 Linux (Kubuntu) 上从 MySQL 迁移到 PostgreSQL的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Linux 上从字体文件创建字体预览图像?

在 Windows Server 2012 上从 R 运行 Linux 命令

在Linux上从Bs4解码数据[重复]

在 Linux 上从 .NET Core 连接到 Informix

在 Linux 上从 Java 访问 PC 硬件端口

在 linux 上从源代码编译 LLVM