Каким способом можно загрузить большой SQL-файл в базу данных?

Добрый день! У меня есть большой SQL-файл объемом более 40 ГБ, который невозможно загрузить через phpMyAdmin. Я загружаю его на сервер по FTP, а затем подключаюсь через Putty по SSH, чтобы выполнить команду: 

```bash
mysql -u****** -p****** ******* < *******.sql 
```
Процесс загрузки начинается, но через некоторое время соединение с сервером прерывается, и, как следствие, загрузка прекращается. 

1. Как можно загрузить большие SQL-файлы?
2. Почему прерывание соединения влияет на процесс загрузки? Разве это не должно сказаться только на клиенте, а не на самом сервере? 

Спасибо!
  • 2 сентября 2024 г. 18:23
Ответы на вопрос 4
Здравствуйте!

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

### 1. Как можно загрузить большие SQL-файлы?

Есть несколько способов загрузить большие SQL-файлы в базу данных, помимо использования `mysql` через SSH:

1. **Использование `mysql` с параметром `--force`:**
   Это может помочь игнорировать некоторые ошибки, хотя не всегда подходит для больших файлов:
   ```bash
   mysql --force -uusername -p database_name < file.sql
   ```

2. **Использование скриптов с разделением файла:**
   Разделите большой SQL-файл на более мелкие части. Это можно сделать с помощью специальных скриптов или утилит. Например, вы можете использовать `split` в Linux:
   ```bash
   split -l 10000 bigfile.sql part_
   ```
   После этого загрузите каждую часть отдельно.

3. **Использование `MySQL` с `--max_allowed_packet`:**
   Убедитесь, что значение параметра `max_allowed_packet` в конфигурации MySQL увеличено до достаточного размера, чтобы справиться с большими запросами.

4. **Использование `MySQL` с параметрами для улучшения производительности:**
   Если вы загружаете много данных, вы можете временно отключить проверку индексов и включить режим `bulk insert`:
   ```sql
   SET autocommit=0;
   SET UNIQUE_CHECKS=0;
   SET FOREIGN_KEY_CHECKS=0;
   -- загрузка данных
   SET FOREIGN_KEY_CHECKS=1;
   SET UNIQUE_CHECKS=1;
   COMMIT;
   ```

5. **Использование утилиты `mysqlimport`:**
   Если данные в формате CSV, вы можете использовать утилиту `mysqlimport`, которая также хорошо работает с большими объемами данных.

6. **Использование `SCREEN` или `Tmux`:**
   Используйте `screen` или `tmux` для управления сессиями. Эти инструменты позволяют вам отсоединяться от сессии и возвращаться к ней позже, даже если соединение прервано.

   Запустите `screen` перед выполнением команды:
   ```bash
   screen
   mysql -uusername -p database_name < file.sql
   ```

### 2. Почему прерывание соединения влияет на процесс загрузки?

Когда вы запускаете команду через SSH, соединение с сервером устанавливается для передачи данных. Если соединение обрывается, сервер не получает дальнейшие данные и останавливает процесс загрузки. 

Клиентская часть (SSH) в данном случае фактически "управляет" последовательностью передачи данных, и когда соединение теряется, MySQL останавливает выполнение запроса, поскольку оно не может получить подтверждение о том, что данные продолжают поступать.

Использование `screen` или `tmux` позволяет вам избежать этой проблемы, так как выполнение команды будет продолжаться на сервере, даже если вы потеряете соединение.

### Итог

Попробуйте методы, описанные выше, чтобы загружать большие SQL-файлы. Особенно полезными будут `screen` и возможно разделение файлов для более удобной загрузки. Если проблема всё равно сохраняется, вы также можете исследовать логи MySQL для поиска возможных ограничений или ошибок.
запусти screen и в нем включи загрузку
Телепатствую. 

Главная причина, чаще всего, это не отключенные индексы, запись в таблицу с ними это n*log(n), а без индексов это n или даже log(n).

Раздели sql на место создания структуры и импорт данных. Замени код создания структуры на такой, чтобы таблицы создавались без индексов, и отдельно создание этих индексов уже после (автоматизировать это не сложно, но чтобы так с ходу найти готовый код я не найду).

Отдельно в sql коде можно расставить commit через некоторое количество (десятки тысяч +-) insert-ов, что бы лог не переполнялся.

Следующий вариант - оптимизация дисковой записи, найди способ принудительно включить lazy writes на диске с базой, например с помощью виртуализации или хотя бы ext4 опция data writeback. Внимание! в этом режиме любая проблема с ос (например отключили питание) испортит данные. Т.е. на время импорта создай файловую систему для таблиц отдельно, потом данные тупо скопируешь. Но если у тебя норм ssd или дисковый контроллер с хорошим кешем, то это не актуально.

И если говорить об самым экстремально большом ускорении, размести файлы базы в tmpfs (оперативка, сотня гигабайт сейчас даже дома не проблема)... Можно для этого арендовать в облаке vps-ку, но желательно в этом же датацентре, а то копировать сотню гигабайт может быть долго. И да, следи за тем что бы была та же архитектура процессора и версия mysql
захожу через putty по SSH и гружу по
mysql -u****** -p****** ******* < *******.sql

Напрасно.
Загрузи CLI, а уж потом в нём грузи дамп командой SOURCE.
Во-первых, не будет тайм-аута, интерактивно клиент, в отличие от безынтерфейсного, не воспринимается как померший, ибо постоянно льёт в выходной поток. Во-вторых, будешь видеть диагностику загрузки (особенно если запустишь CLI с ключом --tee).
Похожие вопросы