Что такое миграции базы данных?

Ответ

Миграции базы данных — это практика управления изменениями схемы БД (структуры таблиц, индексов, отношений) с помощью версионированных скриптов. Это позволяет безопасно и предсказуемо развивать структуру данных вместе с кодом приложения.

Зачем это нужно в Node.js-проектах:

  • Воспроизводимость: Любой разработчик или сервер может привести схему БД к нужному состоянию, выполнив последовательность миграций.
  • Контроль версий: Скрипты миграций хранятся в репозитории вместе с кодом.
  • Безопасное развёртывание: Изменения применяются до запуска нового кода, который от них зависит.
  • Возможность отката: У каждой миграции есть «обратная» функция (down), позволяющая отменить изменения.

Пример миграции с использованием Knex.js (популярный query builder для Node.js):

// migrations/20231015_create_users_table.js

exports.up = function(knex) {
  // Операция применения миграции
  return knex.schema.createTable('users', function(table) {
    table.increments('id').primary();
    table.string('email').notNullable().unique();
    table.string('password_hash').notNullable();
    table.timestamp('created_at').defaultTo(knex.fn.now());
    table.timestamp('updated_at').defaultTo(knex.fn.now());
  });
};

exports.down = function(knex) {
  // Операция отката миграции
  return knex.schema.dropTable('users');
};

Работа с миграциями через CLI:

# Создать новую миграцию
npx knex migrate:make add_role_to_users

# Применить все неприменённые миграции
npx knex migrate:latest

# Откатить последнюю миграцию
npx knex migrate:rollback

В экосистеме Node.js для работы с миграциями также широко используются TypeORM, Sequelize и Prisma.

Ответ 18+ 🔞

А, миграции баз данных! Ну, это такая штука, чтобы твоя база данных не превратилась в дикий, неконтролируемый зоопарк, где таблицы плодятся как кролики, а связи между ними понять может только шаман после трёх литров самогона. Ёпта, представь: ты добавил в код новую фичу, которая требует колонку is_premium в таблице пользователей. Без миграций ты бы лез в pgAdmin или phpMyAdmin, тыкал мышкой, а потом сам от себя охуел, когда на проде забыл это сделать, и всё легло с ошибкой «колонка не найдена». В рот меня чих-пых!

Зачем это в Node.js-проектах, спросишь?

  • Воспроизводимость: Любой новый чувак в команде, или даже сервер на хостинге, может из состояния «пустая база» прийти к нужной версии схемы, просто прогнав скрипты по порядку. Не нужно вручную, блядь, копировать дампы или читать мануал на 50 страниц.
  • Контроль версий: Скрипты миграций живут прямо в гите, рядом с кодом. Видно, кто, когда и зачем добавил ту самую странную колонку parent_id, которая всех потом ебала три месяца.
  • Безопасное развёртывание: Сначала применяются изменения в базе (например, создаётся новая таблица), и только потом запускается новый код приложения, который уже на эту таблицу рассчитывает. Без этого — будет вам хиросима и нигерсраки.
  • Возможность отката: У каждой миграции есть функция down — это как страховочная верёвка. Накосячил что-то в схеме? Да похуй, откатил одну последнюю миграцию, пофиксил баг и накатил заново. Волнение ебать сразу спадает.

Вот тебе пример, как это выглядит на Knex.js (он популярный, логичный):

// migrations/20231015_create_users_table.js

exports.up = function(knex) {
  // Тут мы накатываем миграцию. Создаём таблицу `users`.
  return knex.schema.createTable('users', function(table) {
    table.increments('id').primary(); // Автоинкрементный первичный ключ
    table.string('email').notNullable().unique(); // Почта, уникальная, не пустая
    table.string('password_hash').notNullable(); // Хэш пароля
    table.timestamp('created_at').defaultTo(knex.fn.now()); // Дата создания
    table.timestamp('updated_at').defaultTo(knex.fn.now()); // Дата обновления
  });
};

exports.down = function(knex) {
  // А это — откат. Если что-то пошло не так, просто дропаем таблицу. Жестоко, но честно.
  return knex.schema.dropTable('users');
};

А работать с этим через командную строку — вообще ёперный театр простоты:

# Создаём заготовку для новой миграции. Knex сам сгенерит файлик с timestamp.
npx knex migrate:make add_role_to_users

# Команда-рабочая лошадка. Накатывает все миграции, которые ещё не были применены.
npx knex migrate:latest

# Ой, что-то пошло не так? Откатываем последний пакет миграций.
npx knex migrate:rollback

Кроме Knex, в мире Node.js, конечно, есть и другие монстры: TypeORM, Sequelize, Prisma. У каждого свои заморочки, но суть одна — не дать тебе распиздяйничать со структурой базы и спать чуть спокойнее.