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

发布于 2024-09-01 11:27:46 字数 4297 浏览 5 评论 0原文

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

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

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

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

新希望

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

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

一切顺利。接下来,重新启动服务器并使用以下安装说明配置数据库:

  1. sudo apt-get安装postgresql pgadmin3
  2. sudo /etc/init.d/postgresql-8.4 stop
  3. sudo vi /etc/postgresql/8.4/main/postgresql.conf
  4. 更改data_directory/home/postgres/main
  5. sudo /etc/init.d/postgresql-8.4 start
  6. sudo -u postgres psql postgres code>
  7. \password postgres
  8. sudo -u postgres createdb Climate
  9. pgadmin3

使用 pgadmin3 配置数据库并创建模式。

这一事件在一个名为 bash 的远程 shell 中继续,两个数据库都在运行,并且安装了一组带有相当不寻常徽标的工具:SQL 仙女.

  1. perl Makefile.PL
  2. sudo make install
  3. sudo apt-get install perl-doc (奇怪的是,它不叫perldoc >)
  4. perldoc SQL::Translator::Manual

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

  1. sqlt -f DBI --dsn dbi:mysql:气候 --db-user 用户 --db-password 密码 -t PostgreSQL > Climate-pg-ddl.sql
  2. 编辑 climate-pg-ddl.sql 并将标识符转换为小写,然后插入模式引用(使用 VIM):
    • :%s/"\([A-Z_]*\)"/\L\1/g
    • :%s/表/表气候./g
    • :%s/关于/关于气候。/g
  3. 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 中的表和列重命名为小写可能是值得的:

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

数据库反击

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

  1. pgadmin3(切换到它)
  2. 单击执行任意 SQL 查询图标
  3. 打开 climate-pg-ddl.sql
  4. 搜索 TABLE“ 替换为 TABLE Climate.”(插入架构名称 climate
  5. 在“< /code> 替换为 on Climate." (插入模式名称 climate
  6. F5 执行

这会导致:

Query returned successfully with no result in 122 ms.

Replies of the Jedi

At这一点我很困惑。

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

资源

需要相当多的信息才能达到此目的:

谢谢!

A long time ago on a system far, far away...

Trying to migrate a database from MySQL to PostgreSQL. All the documentation I have read covers, in great detail, how to migrate the structure. I have found very little documentation on migrating the data. The schema has 13 tables (which have been migrated successfully) and 9 GB of data.

MySQL version: 5.1.x
PostgreSQL version: 8.4.x

I want to use the R programming language to analyze the data using SQL select statements; PostgreSQL has PL/R, but MySQL has nothing (as far as I can tell).

A New Hope

Create the database location (/var has insufficient space; also dislike having the PostgreSQL version number everywhere -- upgrading would break scripts!):

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

All good to here. Next, restart the server and configure the database using these installation instructions:

  1. sudo apt-get install postgresql pgadmin3
  2. sudo /etc/init.d/postgresql-8.4 stop
  3. sudo vi /etc/postgresql/8.4/main/postgresql.conf
  4. Change data_directory to /home/postgres/main
  5. sudo /etc/init.d/postgresql-8.4 start
  6. sudo -u postgres psql postgres
  7. \password postgres
  8. sudo -u postgres createdb climate
  9. pgadmin3

Use pgadmin3 to configure the database and create a schema.

The episode continues in a remote shell known as bash, with both databases running, and the installation of a set of tools with a rather unusual logo: SQL Fairy.

  1. perl Makefile.PL
  2. sudo make install
  3. sudo apt-get install perl-doc (strangely, it is not called perldoc)
  4. perldoc SQL::Translator::Manual

Extract a PostgreSQL-friendly DDL and all the MySQL data:

  1. sqlt -f DBI --dsn dbi:mysql:climate --db-user user --db-password password -t PostgreSQL > climate-pg-ddl.sql
  2. Edit climate-pg-ddl.sql and convert the identifiers to lowercase, and insert the schema reference (using VIM):
    • :%s/"\([A-Z_]*\)"/\L\1/g
    • :%s/ TABLE / TABLE climate./g
    • :%s/ on / on climate./g
  3. 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

It might be worthwhile to simply rename the tables and columns in MySQL to lowercase:

  1. select concat( 'RENAME TABLE climate.', TABLE_NAME, ' to climate.', lower(TABLE_NAME), ';' ) from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='climate';
  2. Execute the commands from the previous step.
  3. There is probably a way to do the same for columns; I changed them manually because it was faster than figuring out how to write the query.

The Database Strikes Back

Recreate the structure in PostgreSQL as follows:

  1. pgadmin3 (switch to it)
  2. Click the Execute arbitrary SQL queries icon
  3. Open climate-pg-ddl.sql
  4. Search for TABLE " replace with TABLE climate." (insert the schema name climate)
  5. Search for on " replace with on climate." (insert the schema name climate)
  6. Press F5 to execute

This results in:

Query returned successfully with no result in 122 ms.

Replies of the Jedi

At this point I am stumped.

  • Where do I go from here (what are the steps) to convert climate-my.sql to climate-pg.sql so that they can be executed against PostgreSQL?
  • How to I make sure the indexes are copied over correctly (to maintain referential integrity; I don't have constraints at the moment to ease the transition)?
  • How do I ensure that adding new rows in PostgreSQL will start enumerating from the index of the last row inserted (and not conflict with an existing primary key from the sequence)?
  • How do you ensure the schema name comes through when transforming the data from MySQL to PostgreSQL inserts?

Resources

A fair bit of information was needed to get this far:

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

打小就很酷 2024-09-08 11:27:46

我通常为此类迁移做两件事:

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

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

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

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

如果您只是使用 sed 脚本将 SQL 转储从一种格式转换为另一种格式,那么您只需执行以下操作:我们正在做的是将 MySQL 数据库放入 PostgreSQL 服务器中。您可以这样做,而且这样做仍然会有一些好处,但如果您要迁移,请完全迁移。

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

What I usually do for such migrations is two-fold:

  • Extract the whole database definition from MySQL and adapt it to PostgreSQL syntax.
  • Go over the database definition and transform it to take advantage of functionality in PostgreSQL that doesn't exist in MySQL.

Then do the conversion, and write a program in whatever language you are most comfortable with that accomplishes the following:

  • Reads the data from the MySQL database.
  • Performs whatever transformation is necessary on the data to be stored in the PostgreSQL database.
  • Saves the now-transformed data in the PostgreSQL database.

Redesign the tables for PostgreSQL to take advantage of its features.

If you just do something like use a sed script to convert the SQL dump from one format to the next, all you are doing is putting a MySQL database in a PostgreSQL server. You can do that, and there will still be some benefit from doing so, but if you're going to migrate, migrate fully.

It will involve a little bit more up-front time spent, but I have yet to come across a situation where it isn't worth it.

狂之美人 2024-09-08 11:27:46

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

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

  1. 转义引号。

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

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

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

  3. 连接到数据库。

    sudo su - postgres
    psql Climate

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

    \编码 iso-8859-1
    \i Climate-pg.sql

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

索引、主键和序列

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

导入后设置序列

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

架构前缀

无需为表添加架构名称前缀。使用:

SET search_path TO climate;

Convert the mysqldump file to a PostgreSQL-friendly format

Convert the data as follows (do not use mysql2pgsql.perl):

  1. Escape the quotes.

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

  2. Replace the USE "climate"; with a search path and comment the comments:

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

  3. Connect to the database.

    sudo su - postgres
    psql climate

  4. Set the encoding (mysqldump ignores its encoding parameter) and then execute the script.

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

This series of steps will probably not work for complex databases with many mixed types. However, it works for integers, varchars, and floats.

Indexes, primary keys, and sequences

Since mysqldump included the primary keys when generating the INSERT statements, they will trump the table's automatic sequence. The sequences for all tables remained 1 upon inspection.

Set the sequence after import

Using the ALTER SEQUENCE command will set them to whatever value is needed.

Schema Prefix

There is no need to prefix tables with the schema name. Use:

SET search_path TO climate;
一笔一画续写前缘 2024-09-08 11:27:46

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

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

    pg_dump 数据库名称> /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/mysqlconfigure --prefix=/tmp/mysql && make install 应该做)并使用 /tmp/mysql/bin/mysqldump

  • 导入架构的其余部分:

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

If you've converted a schema then migrating data would be the easy part:

  • dump schema from PostgreSQL (you said that you've converted schema to postgres, so we will dump it for now, as we will be deleting and recreating target database, to have it cleaned):

    pg_dump dbname > /tmp/dbname-schema.sql
    
  • split schema to 2 parts — /tmp/dbname-schema-1.sql containing create table statements, /tmp/dbname-schema-2.sql — the rest. PostgreSQL needs to import data before foreign keys, triggers etc. are imported, but after table definitions are imported.

  • recreate database with only 1 part of schema:

    drop database dbname
    create database dbname
    \i /tmp/dbname-schema-1.sql
    -- now we have tables without data, triggers, foreign keys etc.
    
  • import data:

    (
       echo 'start transaction';
       mysqldump --skip-quote-names dbname | grep ^INSERT;
       echo 'commit'
    ) | psql dbname
    -- now we have tables with data, but without triggers, foreign keys etc.
    

    A --skip-quote-names option is added in MySQL 5.1.3, so if you have older version, then install newer mysql temporarily in /tmp/mysql (configure --prefix=/tmp/mysql && make install should do) and use /tmp/mysql/bin/mysqldump.

  • import the rest of schema:

    psql dbname
    start transaction
    \i /tmp/dbname-schema-2.sql
    commit
    -- we're done
    
冧九 2024-09-08 11:27:46

查看 etlalchemy。它允许您用 4 行 Python 代码从 MySQL 迁移到 PostgreSQL,或者在几个其他数据库之间迁移。您可以在此处了解更多相关信息。

安装: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()

Check out etlalchemy. It allows you migrate from MySQL to PostgreSQL, or between several other databases, in 4 lines of Python. You can read more about it here.

To install: pip install etlalchemy

To run:

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文