---
title: "Конвертация MySQL в PostgreSQL"
description: "Конвертируйте дамп MySQL или MariaDB в скрипт PostgreSQL, который загружается с первой попытки, с отчетом о каждом изменении. В браузере, дамп не покидает компьютер."
canonical: https://intosql.com/ru/mysql-v-postgresql
last_updated: 2026-10-15
---

# Конвертация MySQL в PostgreSQL

Перетащите дамп из mysqldump, mariadb-dump, mysqlpump, phpMyAdmin или Adminer в формате .sql или .sql.gz и скачайте скрипт PostgreSQL с теми же таблицами, ключами, индексами и данными. Каждое значение, которое PostgreSQL не может хранить как есть, и каждый объект, который он не переносит, указаны в отчете.

## Что меняется при переходе с MySQL на PostgreSQL

Каждая строка - это правило, которое применяет конвертер, и строка отчета, которую он пишет, когда правило что-то меняет в ваших данных.

| В MySQL | В PostgreSQL | Строка отчета |
| --- | --- | --- |
| TINYINT(1), BOOL | boolean, если каждое значение 0 или 1, иначе smallint | `bool_kept_numeric` |
| UNSIGNED integers | следующий более широкий целый тип с CHECK на неотрицательность; BIGINT UNSIGNED становится bigint, если все значения помещаются, иначе numeric(20,0) | `unsigned_widened` |
| ZEROFILL and display widths | удаляется | `zerofill_dropped` |
| FLOAT(M,D) | real или double precision, без масштаба | `float_scale_dropped` |
| BIT(1), BIT(n) | boolean, bit(n) |  |
| zero, partial or impossible dates (0000-00-00, 2024-02-30) | NULL | `invalid_date_null` |
| NOT NULL columns with values that become NULL | NOT NULL снимается | `not_null_relaxed` |
| DEFAULT '0000-00-00' | без значения по умолчанию | `zero_date_default` |
| TIME | time, если каждое значение укладывается в сутки, иначе interval | `time_as_interval` |
| YEAR | smallint с CHECK диапазона |  |
| CHAR(n) | varchar(n) |  |
| DATETIME | timestamp |  |
| TIMESTAMP | timestamptz в часовом поясе, указанном в дампе, или UTC, если он не указан | `timestamp_zone_assumed` |
| ENUM | text с CHECK значений |  |
| ENUM holding '' (MySQL's error value) | пустое значение, которое допускает проверка | `enum_invalid_value` |
| ENUM or SET holding values outside its list | без CHECK | `enum_check_skipped` |
| SET | text[] с CHECK, что каждый элемент есть в списке |  |
| JSON | jsonb; json, если значение содержит \u0000 | `json_not_jsonb` |
| NUL bytes in text | удаляется | `nul_removed` |
| text that isn't valid in its character set | неверные байты заменяются символом замены | `invalid_utf8_replaced` |
| text decoded twice (Ã±) | копируется как есть | `mojibake_suspected` |
| AUTO_INCREMENT | GENERATED BY DEFAULT AS IDENTITY, счетчик выставлен после скопированных id |  |
| MyISAM AUTO_INCREMENT on the second column of a key | один счетчик на таблицу | `myisam_group_autoincrement` |
| ON UPDATE CURRENT_TIMESTAMP | триггер BEFORE UPDATE | `on_update_trigger` |
| generated columns | STORED | `virtual_as_stored` |
| generated columns with functions PostgreSQL lacks | обычный столбец | `generated_not_translated` |
| INVISIBLE columns | обычные столбцы | `invisible_column` |
| CHECK constraints | переводится, внутри CREATE TABLE |  |
| CHECK constraints with functions PostgreSQL lacks | не создается | `check_skipped` |
| CHECK ... NOT ENFORCED | не создается | `check_not_enforced` |
| defaults with functions PostgreSQL lacks | без значения по умолчанию | `default_not_translated` |
| keys and indexes on a prefix, c(20) | индекс по left(c, 20) | `prefix_unique` |
| FULLTEXT indexes | GIN по to_tsvector('simple', ...) | `fulltext_as_gin` |
| indexes on values over 2,000 bytes | hash | `index_on_wide_values` |
| SPATIAL indexes | не создается без PostGIS | `spatial_index_skipped` |
| functional indexes PostgreSQL can't write | не создается | `index_skipped` |
| foreign keys | после данных, NOT VALID, затем проверка с предупреждением о строках без родителя |  |
| foreign keys to columns without a unique key | не создается | `foreign_key_skipped` |
| table and column names | нижний регистр, если имена остаются уникальными | `identifier_renamed` |
| names over 63 bytes | сокращается с хешем | `name_shortened` |
| GEOMETRY, POINT, POLYGON... | WKB в bytea | `geometry_as_wkb` |
| INET4, INET6, UUID (MariaDB) | inet, uuid |  |
| BINARY, VARBINARY, BLOB | bytea |  |
| PARTITION BY | одна таблица | `partitions_dropped` |
| WITH SYSTEM VERSIONING (MariaDB) | таблица с текущими строками | `system_versioning_dropped` |
| MyISAM, MEMORY and other engines | обычная таблица | `engine_dropped` |
| views, triggers, procedures, functions and events | перечисляются в отчете | `not_converted_objects` |
| dumps without CREATE TABLE | типы определяются по значениям | `no_schema` |
| geometries in a dump without CREATE TABLE | WKB в bytea | `geometry_inferred` |
| _ci collations | точное сравнение | `case_insensitive_collation` |
| SET NAMES utf8 from utf8mb4 tables | конвертируется с предупреждением | `dump_lost_four_byte_chars` |
| dumps without SET NAMES whose text isn't UTF-8 | читается как Latin-1 (Windows-1252) | `charset_guessed` |
| sjis, cp932, gbk, big5 dumps | читается как UTF-8, с предупреждением | `unsupported_charset` |
| UNHEX('..'), CONVERT(b'..', UNSIGNED), CONVERT(".." USING x), ST_GeomFromText('..') in rows | вычисляются |  |
| other expressions in rows | NULL | `expression_value` |
| DEFAULT in VALUES | значение столбца по умолчанию | `default_keyword_filled` |
| DEFAULT in VALUES without a literal default | NULL | `default_keyword_null` |
| REPLACE and INSERT IGNORE | обычные строки | `replace_as_insert` |
| types IntoSQL doesn't know | text | `unknown_type` |
| values that don't fit their column | NULL | `invalid_value_null` |
| unreadable geometries | NULL | `bad_geometry` |
| CREATE SEQUENCE (MariaDB) | CREATE SEQUENCE с текущим значением |  |

## Загрузите скрипт в PostgreSQL

Скрипт создает таблицы, копирует строки, затем добавляет ключи, индексы и внешние ключи, поэтому загрузка идет быстро и останавливается на первой ошибке.

```shell
psql -v ON_ERROR_STOP=1 -d mydb -f mysql.postgresql.sql
```

Внешние ключи добавляются как NOT VALID, а затем проверяются. Если строка ссылается на несуществующую строку, скрипт сообщает, какое ограничение нарушено, а не прерывается на полпути.

Для большого дампа сначала создайте базу данных и запустите скрипт через psql на той же машине, где работает сервер.

## Как создать дамп MySQL для лучшего результата

Конвертер читает то, что есть в дампе. Эти параметры сохраняют в нем больше ваших данных:

- --default-character-set=utf8mb4 сохраняет эмодзи и другие 4-байтовые символы, которые дамп в utf8 теряет еще до конвертера.
- --hex-blob записывает двоичные столбцы в шестнадцатеричном виде, который не портится при копировании между системами.
- --routines --triggers --events добавляют эти объекты в дамп, чтобы отчет мог их перечислить.

## Что не конвертируется

Представления, триггеры, хранимые процедуры, функции и события написаны на собственном языке каждой базы данных. Они перечислены в отчете по имени и никогда не удаляются молча, чтобы вы могли переписать их для PostgreSQL.

## Сравнение с pgloader

Одни и те же дампы, конвертированные и загруженные IntoSQL и pgloader 3.6.7 на одной машине (10-ядерный i9-10900K с SATA SSD) в октябре 2026 года.

- Столбец TINYINT(1) со значениями 2, -1 и -5: pgloader загружает для каждого true, без предупреждения. IntoSQL сохраняет числа, а отчет объясняет почему.
- Дамп со значением по умолчанию 'it's', таблицей с обратной кавычкой в имени, ENUM с пустым значением и TIME больше 24 часов: pgloader останавливается. IntoSQL конвертирует и загружает его.
- В том, что загружает pgloader, теряются первичные, уникальные и внешние ключи и identity. IntoSQL сохраняет их все.
- Дамп 5.3 GB на 30 миллионов строк: pgloader требует сначала восстановить его в работающий MySQL, что занимает 18 минут, а затем с настройками по умолчанию ему не хватает памяти. IntoSQL конвертирует дамп за 10 секунд, а psql загружает скрипт примерно за 3 минуты.
- 476 дампов из MySQL с 5.5 по 9 и MariaDB с 10.3 по 12, загруженных в PostgreSQL 13 и 18: ни одной ошибки загрузки, и ни одно значение не изменилось без строки в отчете.

## Вопросы о MySQL в PostgreSQL

### Мой дамп загружается на сервер?

Нет. Конвертер работает в вашем браузере и читает дамп с диска по частям, поэтому он никогда не покидает ваш компьютер. Приложение для компьютера и командная строка тоже конвертируют на вашем компьютере.

### Насколько большим может быть дамп?

Конвертер никогда не держит весь дамп в памяти: он читает файл дважды, по диапазонам, и пишет скрипт по ходу чтения. Дампы в несколько гигабайт конвертируются в браузере, в приложении для компьютера и в командной строке.

### Читает ли он дампы MariaDB?

Да. Дампы из mariadb-dump и из MariaDB с 10.3 по 12 конвертируются так же, включая столбцы INET6, INET4 и UUID в MariaDB.

### Что происходит с датами 0000-00-00?

В PostgreSQL нет нулевой даты, поэтому они становятся NULL, а столбец допускает NULL. Отчет показывает, сколько их было в каждом столбце.

### Сохраняются ли значения AUTO_INCREMENT?

Да. Каждый столбец AUTO_INCREMENT становится столбцом identity, каждая строка сохраняет свой id, а следующий id идет после наибольшего или после AUTO_INCREMENT таблицы, если он больше.

### Становится ли TINYINT(1) типом boolean?

Только если каждое значение в столбце равно 0 или 1. Если в нем есть другие числа, например 2 или -1, он остается числом, а отчет объясняет почему, так что ни одно значение случайно не станет true.

### А хранимые процедуры и триггеры?

Они перечислены в отчете по имени и не конвертируются, потому что каждая база данных пишет их на своем языке. Исключение - ON UPDATE CURRENT_TIMESTAMP: он становится триггером PostgreSQL.

### На каких версиях PostgreSQL загружается скрипт?

PostgreSQL с 13 по 18. Один и тот же скрипт загружается на каждой из них и останавливается на первой ошибке, если что-то пойдет не так.

## Другие конвертации в PostgreSQL

- [Конвертация Excel в PostgreSQL](https://intosql.com/ru/excel-v-postgresql)
- [Конвертация CSV в PostgreSQL](https://intosql.com/ru/csv-v-postgresql)
- [Конвертация JSON в PostgreSQL](https://intosql.com/ru/json-v-postgresql)
