Реализация архивирования старых данных базы данных

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация архивирования старых данных базы данных
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1227
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    859
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1074
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    829
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    833

Реализация архивирования старых данных базы данных

Таблица events с 500 миллионами строк и ростом 2 миллиона в сутки — это проблема, которая становится острее каждый день. SELECT тормозит, VACUUM не успевает, индексы занимают гигабайты. Архивирование решает задачу: горячие данные остаются в основной базе, холодные переезжают в архив с другим режимом хранения.

Стратегии архивирования

Partition detach — если таблица партиционирована, старые партиции отсоединяются и переносятся в архивную базу или tablespace. Самый быстрый подход.

INSERT + DELETE батчами — для непартиционированных таблиц. Копируем строки в архивную таблицу батчами, удаляем из основной. Не создаёт длинных транзакций.

Логическая реплика — настраиваем publication на основной базе, subscription на архивной, с фильтром по дате. Архив обновляется в реальном времени.

Dump + truncate — экспорт в CSV/parquet, удаление из базы. Данные больше не в PostgreSQL/MySQL — только в файловом архиве.

PostgreSQL: батчевое перемещение

-- Архивная таблица (может быть в отдельной схеме или базе)
CREATE TABLE archive.events (
    LIKE public.events INCLUDING ALL
);

-- Функция архивирования с батчами
CREATE OR REPLACE FUNCTION archive_old_events(
    p_before_date  TIMESTAMPTZ,
    p_batch_size   INTEGER DEFAULT 10000
) RETURNS TABLE(batches_processed INTEGER, rows_archived BIGINT)
LANGUAGE plpgsql AS $$
DECLARE
    v_batches  INTEGER := 0;
    v_total    BIGINT  := 0;
    v_moved    INTEGER;
BEGIN
    LOOP
        -- Переносим один батч в архив
        WITH moved AS (
            DELETE FROM public.events
            WHERE id IN (
                SELECT id FROM public.events
                WHERE created_at < p_before_date
                LIMIT p_batch_size
                FOR UPDATE SKIP LOCKED  -- пропускаем заблокированные строки
            )
            RETURNING *
        )
        INSERT INTO archive.events SELECT * FROM moved;

        GET DIAGNOSTICS v_moved = ROW_COUNT;
        EXIT WHEN v_moved = 0;

        v_batches := v_batches + 1;
        v_total   := v_total + v_moved;

        -- Пауза между батчами — не перегружаем диск
        PERFORM pg_sleep(0.1);

        -- Прогресс
        RAISE NOTICE 'Batch %: % rows archived (total: %)', v_batches, v_moved, v_total;
    END LOOP;

    RETURN QUERY SELECT v_batches, v_total;
END $$;

Запуск:

SELECT * FROM archive_old_events('2024-01-01'::timestamptz, 10000);
-- Batch 1: 10000 rows archived (total: 10000)
-- Batch 2: 10000 rows archived (total: 20000)
-- ...

SKIP LOCKED позволяет запускать несколько параллельных воркеров без конфликтов.

Планировщик: Artisan команда

// app/Console/Commands/ArchiveOldData.php
class ArchiveOldData extends Command
{
    protected $signature   = 'db:archive {--days=365 : Архивировать данные старше N дней}';
    protected $description = 'Archive old records to archive tables';

    public function handle(): int
    {
        $beforeDate = now()->subDays($this->option('days'))->toDateTimeString();

        $this->info("Archiving events before {$beforeDate}...");

        $result = DB::selectOne(
            'SELECT * FROM archive_old_events(?::timestamptz, 5000)',
            [$beforeDate]
        );

        $this->info("Done: {$result->batches_processed} batches, {$result->rows_archived} rows");

        // VACUUM после массового удаления
        DB::statement('VACUUM ANALYZE events');

        return self::SUCCESS;
    }
}
// app/Console/Kernel.php
$schedule->command('db:archive --days=180')
    ->monthlyOn(1, '02:00')  // первое число каждого месяца в 2:00
    ->withoutOverlapping()
    ->onFailure(fn() => Notification::route('telegram', config('services.telegram.ops_chat'))
        ->notify(new ArchivingFailedNotification()));

MySQL: архивирование с pt-archiver

Percona Toolkit предоставляет pt-archiver — инструмент для переноса строк между таблицами или в файл:

# Перенос в архивную таблицу
pt-archiver \
  --source  h=localhost,D=mydb,t=events,u=root,p=password \
  --dest    h=localhost,D=archive_db,t=events,u=root,p=password \
  --where   "created_at < '2024-01-01'" \
  --limit   5000 \
  --sleep   0.1 \
  --no-delete  # сначала только копируем; после проверки добавить --purge

# С удалением из источника
pt-archiver \
  --source  h=localhost,D=mydb,t=events \
  --where   "created_at < '2024-01-01'" \
  --limit   5000 \
  --sleep   0.1 \
  --purge  # удалять после копирования

# Только удаление без архива (если данные уже перенесены)
pt-archiver \
  --source  h=localhost,D=mydb,t=events \
  --where   "created_at < '2024-01-01'" \
  --limit   10000 \
  --purge \
  --no-safe-auto-increment

Архивирование через PostgreSQL COPY в файл

Для долгосрочного хранения без доступа через SQL:

#!/bin/bash
# /opt/scripts/archive_events.sh

YEAR_MONTH=$1  # например: 2024-01
DB=mydb
ARCHIVE_DIR=/mnt/archive/events

mkdir -p "${ARCHIVE_DIR}/${YEAR_MONTH}"

# Экспорт в gzip CSV
psql -d "$DB" -c \
  "COPY (SELECT * FROM events WHERE created_at >= '${YEAR_MONTH}-01' AND created_at < '$(date -d "${YEAR_MONTH}-01 +1 month" +%Y-%m-%d)') TO STDOUT CSV HEADER" \
  | gzip > "${ARCHIVE_DIR}/${YEAR_MONTH}/events_${YEAR_MONTH}.csv.gz"

echo "Exported: $(stat -c%s ${ARCHIVE_DIR}/${YEAR_MONTH}/events_${YEAR_MONTH}.csv.gz) bytes"

# Проверяем, что файл не пустой
if [ $(stat -c%s "${ARCHIVE_DIR}/${YEAR_MONTH}/events_${YEAR_MONTH}.csv.gz") -gt 1000 ]; then
    psql -d "$DB" -c \
      "DELETE FROM events WHERE created_at >= '${YEAR_MONTH}-01' AND created_at < '$(date -d "${YEAR_MONTH}-01 +1 month" +%Y-%m-%d)'"
    echo "Deleted from events table"
else
    echo "ERROR: archive file too small, skipping delete"
    exit 1
fi

Архивная база на отдельном хранилище

Архивные данные можно хранить в отдельной PostgreSQL с включённым сжатием:

-- На архивном сервере: включить сжатие страниц (PostgreSQL 14+ с pglz)
-- Или использовать TOAST компрессию для JSONB/TEXT

-- Tablespace на дешёвом HDD или NFS
CREATE TABLESPACE archive_ts LOCATION '/mnt/slow_storage/pgsql';
CREATE TABLE archive.events TABLESPACE archive_ts (LIKE public.events);

Политика хранения данных

Рекомендуется документировать политику явно:

Таблица Горячие данные Архив Удаление
events 90 дней 2 года (CSV.gz) после 2 лет
sessions 30 дней не архивируется удаление
orders всегда никогда
logs 14 дней 1 год после 1 года

Политика согласовывается с требованиями бизнеса и регулятора (GDPR, 152-ФЗ).

Восстановление из архива

# Восстановить данные из CSV-архива обратно в базу
gunzip -c /mnt/archive/events/2024-01/events_2024-01.csv.gz | \
  psql -d mydb -c "COPY events FROM STDIN CSV HEADER"

Из партиционированной архивной таблицы — ATTACH PARTITION к основной таблице без копирования данных.

Сроки реализации

Базовое архивирование батчами с Artisan-командой и расписанием: 1–2 дня. Полная система с мониторингом, политиками хранения, восстановлением из архива и обработкой ошибок: 3–5 дней.