在 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.conf
将data_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
(奇怪的是不叫perldoc
)
perldoc 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 - postgres
psql climate
设置编码(mysqldump忽略其编码参数),然后执行脚本。
\encoding iso-8859-1
\i climate-pg.sql
这一系列步骤可能不适用于具有多种混合类型的复杂数据库。但是,它适用于 integer
s、varchar
s 和 float
s。
索引、主键和序列
由于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的主要内容,如果未能解决你的问题,请参考以下文章
在 Windows Server 2012 上从 R 运行 Linux 命令