cdcdb/source/cdcdb/db/scheme.md

197 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Схемы базы данных для хранения снимков (фрагментов)
## Структура базы данных
```mermaid
erDiagram
%% Композитный PK у SNAPSHOT_CHUNKS: (snapshot_id, chunk_index)
SNAPSHOTS {
int id PK
string label
string created_utc
int source_length
int algo_min
int algo_normal
int algo_max
int mask_s
int mask_l
string status
}
BLOBS {
string sha256 PK
int size
blob content
string created_utc
}
SNAPSHOT_CHUNKS {
int snapshot_id FK
int chunk_index
int offset
int size
string sha256 FK
}
%% Связи и поведение внешних ключей
SNAPSHOTS ||--o{ SNAPSHOT_CHUNKS : "1:N, ON DELETE CASCADE"
BLOBS ||--o{ SNAPSHOT_CHUNKS : "1:N, ON DELETE RESTRICT"
```
## Схема последовательности записи в базу данных
```mermaid
sequenceDiagram
autonumber
participant APP as Приложение
participant CH as Разбиение на чанки (FastCDC)
participant HS as Хеширование (SHA-256)
participant DB as База данных (SQLite)
Note over APP,DB: Подготовка
APP->>DB: Открывает соединение, включает PRAGMA (WAL, foreign_keys=ON)
APP->>DB: BEGIN IMMEDIATE (начать транзакцию с блокировкой на запись)
Note over APP,DB: Создание метаданных снимка
APP->>DB: INSERT INTO snapshots(label, source_length, algo_min, algo_normal, algo_max, mask_s, mask_l, status='pending')
DB-->>APP: id снимка = last_insert_rowid()
Note over APP,CH: Поток файла → чанки
APP->>CH: Читает файл, передает параметры FastCDC (min/normal/max, mask_s/mask_l)
loop Для каждого чанка в порядке следования
CH-->>APP: Возвращает {chunk_index, offset, size, bytes}
Note over APP,HS: Хеш содержимого
APP->>HS: Вычисляет SHA-256(bytes)
HS-->>APP: digest (sha256)
Note over APP,DB: Дедупликация контента
APP->>DB: SELECT 1 FROM blobs WHERE sha256 = ?
alt Блоб отсутствует
APP->>DB: INSERT INTO blobs(sha256, size, content)
DB-->>APP: OK
else Блоб уже есть
DB-->>APP: Найден (пропускаем вставку содержимого)
end
Note over APP,DB: Привязка чанка к снимку
APP->>DB: INSERT INTO snapshot_chunks(snapshot_id, chunk_index, offset, size, sha256)
DB-->>APP: OK (PK: (snapshot_id, chunk_index))
end
Note over APP,DB: Валидация и завершение
APP->>DB: SELECT SUM(size) FROM snapshot_chunks WHERE snapshot_id = ?
DB-->>APP: total_size
alt total_size == snapshots.source_length
APP->>DB: UPDATE snapshots SET status='ready' WHERE id = ?
APP->>DB: COMMIT
DB-->>APP: Транзакция зафиксирована
else Несоответствие размеров или ошибка
APP->>DB: ROLLBACK
DB-->>APP: Откат изменений
APP-->>APP: Логирует ошибку, возвращает код/исключение
end
```
## Схема последовательности восстановления из базы данных
```mermaid
sequenceDiagram
autonumber
participant APP as Приложение
participant DB as База данных (SQLite)
participant FS as Целевой файл
participant HS as Хеширование (опц.)
Note over APP,DB: Подготовка к чтению
APP->>DB: Открывает соединение (read), BEGIN (снимок чтения)
Note over APP,DB: Выбор снимка
APP->>DB: Находит нужный снимок по id/label, читает status и source_length
DB-->>APP: id, status, source_length
alt status == "ready"
else снимок не готов
APP-->>APP: Прерывает восстановление с ошибкой
DB-->>APP: END
end
Note over APP,DB: Получение состава снимка
APP->>DB: SELECT chunk_index, offset, size, sha256 FROM snapshot_chunks WHERE snapshot_id=? ORDER BY chunk_index
DB-->>APP: Строки чанков в порядке chunk_index
loop Для каждого чанка
APP->>DB: SELECT content, size FROM blobs WHERE sha256=?
DB-->>APP: content, blob_size
Note over APP,HS: (опц.) контроль целостности чанка
APP->>HS: Вычисляет SHA-256(content)
HS-->>APP: digest
APP-->>APP: Сверяет digest с sha256 и size с blob_size
alt offset задан
APP->>FS: Позиционируется на offset и пишет content (pwrite/seek+write)
else offset отсутствует
APP->>FS: Дописывает content в конец файла
end
end
Note over APP,DB: Финальная проверка
APP-->>APP: Суммирует размеры записанных чанков → total_size
APP->>DB: Берёт snapshots.source_length
DB-->>APP: source_length
alt total_size == source_length
APP->>FS: fsync и close
DB-->>APP: END
APP-->>APP: Успешное восстановление
else размеры не совпали
APP->>FS: Удаляет/помечает файл как повреждённый
DB-->>APP: END
APP-->>APP: Фиксирует ошибку (несоответствие сумм)
end
```
## Схема записи в БД
```mermaid
sequenceDiagram
autonumber
participant APP as Приложение
participant DB as SQLite
participant CH as Разбиение (FastCDC)
participant HS as SHA-256
Note over APP,DB: Подготовка к записи
APP->>DB: PRAGMA foreign_keys=ON
APP->>DB: BEGIN IMMEDIATE
Note over APP,DB: Метаданные снимка
APP->>DB: INSERT INTO snapshots(..., status='pending')
DB-->>APP: snap_id := last_insert_rowid()
Note over APP,CH: Поток файла → чанки (min/normal/max, mask_s/mask_l)
loop Для каждого чанка по порядку
CH-->>APP: {chunk_index, offset, size, bytes}
Note over APP,HS: Хеширование
APP->>HS: SHA-256(bytes)
HS-->>APP: sha256 (32 байта)
Note over APP,DB: Дедупликация содержимого
APP->>DB: INSERT INTO blobs(sha256,size,content) ON CONFLICT DO NOTHING
DB-->>APP: OK (новая строка или уже была)
Note over APP,DB: Привязка к снимку
APP->>DB: INSERT INTO snapshot_chunks(snapshot_id,chunk_index,offset,size,sha256)
DB-->>APP: OK (триггер ++refcount, last_seen_utc=now)
end
Note over APP,DB: Валидация и финал
APP->>DB: SELECT SUM(size) FROM snapshot_chunks WHERE snapshot_id = snap_id
DB-->>APP: total_size
alt total_size == snapshots.source_length
Note over DB: триггер mark_ready ставит status='ready'
APP->>DB: COMMIT
else несовпадение / ошибка
APP->>DB: ROLLBACK
end
```