Что такое Soft Delete (мягкое удаление) в базах данных?

«Что такое Soft Delete (мягкое удаление) в базах данных?» — вопрос из категории Базы данных, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Soft Delete (мягкое удаление) — это паттерн, при котором запись в базе данных не удаляется физически оператором DELETE, а помечается как удалённая с помощью специального флага (например, колонки deleted_at типа TIMESTAMP или is_deleted типа BOOLEAN). Это позволяет сохранять данные для истории, аудита или возможности восстановления.

Типичная реализация:

  1. В таблицу добавляется поле deleted_at (NULL по умолчанию).
  2. При "удалении" в это поле записывается текущая дата и время (вместо настоящего удаления).
  3. Все основные выборки (SELECT) автоматически фильтруют записи по условию WHERE deleted_at IS NULL.

Пример на SQL:

-- Создание таблицы
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100),
    deleted_at TIMESTAMP NULL DEFAULT NULL
);

-- "Мягкое" удаление пользователя с id = 5
UPDATE users SET deleted_at = NOW() WHERE id = 5;

-- Выборка только активных пользователей
SELECT * FROM users WHERE deleted_at IS NULL;

-- Выборка всех пользователей, включая удалённых
SELECT * FROM users;

-- Восстановление пользователя
UPDATE users SET deleted_at = NULL WHERE id = 5;

Реализация в Laravel Eloquent: Laravel предоставляет трейт SoftDeletes для удобной работы с этим паттерном.

// В модели
use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentSoftDeletes;

class User extends Model {
    use SoftDeletes; // Добавляет функциональность мягкого удаления
    protected $dates = ['deleted_at'];
}

// Использование
$user = User::find(1);
$user->delete(); // Заполняет колонку `deleted_at` текущей датой

// Стандартные запросы игнорируют удалённые записи
$activeUsers = User::all(); // Только где deleted_at IS NULL

// Для работы со всеми записями
$allUsers = User::withTrashed()->get();
$trashedUsers = User::onlyTrashed()->get();

// Восстановление
User::withTrashed()->find(1)->restore(); // Обнуляет deleted_at

// Полное физическое удаление
User::withTrashed()->find(1)->forceDelete();

Преимущества Soft Delete:

  • Безопасность данных: Возможность восстановить случайно удалённые данные.
  • Целостность ссылок: Внешние ключи не нарушаются, так как запись физически остаётся в таблице.
  • Аудит: Сохраняется полная история всех записей.

Недостатки и сложности:

  • Усложнение запросов: Необходимо всегда помнить о фильтрации по deleted_at. В Laravel это решается на уровне ORM.
  • Рост базы данных: Требуется периодическая архивация или очистка старых "удалённых" записей.
  • Уникальные индексы: Могут возникнуть конфликты, если уникальность должна учитывать только активные записи. Решение — использовать составные индексы, включающие deleted_at.