раздел 10
Databases
СУБД из CLI, ACID, индексы и EXPLAIN, MVCC и WAL, Redis и ClickHouse, CDC и lakehouse. От psql до архитектуры данных.
Начать раздел
Хочу пройти
Не получилось изменить список. Попробуй ещё раз.
Без входа у каждого урока видно начало. Войди, чтобы читать целиком, отмечать пройденное и решать задачи. войти
Мастерская: Своя СУБД на TS
Мастерская: Своя СУБД на Effect
Мастерская: Своя СУБД на Go
Мастерская: Своя СУБД на Rust
Мастерская: Своя СУБД на Haskell
Уроки раздела
Теория · введение
Теория · реляционная модель
Теория · реляционная алгебра
Теория · ER-моделирование
Теория · нормализация
Теория · транзакции
Теория · физический уровень
Теория · современный ландшафт
SQL · основы выборки
SQL · JOIN-ы
SQL · агрегация
SQL · подзапросы и окна
SQL · классические задачи
SQL · производительность и проектирование
Junior
Middle
Внутренности
Спец-БД
Архитектура данных
Workshop · СУБД на TS
Изделие «Своя СУБД на TS», крейт ourdb
- Своя СУБД на TS · урок 1: страницы и свой файловый слой
- Своя СУБД на TS · урок 2: буферный пул
- Своя СУБД на TS · урок 3: куча и записи
- Своя СУБД на TS · урок 4: B+Tree индекс
- Своя СУБД на TS · урок 5: свой SQL, лексер и парсер
- Своя СУБД на TS · урок 6: анализ, план, исполнитель, EXPLAIN
- Своя СУБД на TS · урок 7: журнал упреждающей записи и восстановление
- Своя СУБД на TS · урок 8: транзакции, откат и видимость
- Своя СУБД на TS · урок 9: конкуренция, блокировки и дедлоки
- Своя СУБД на TS · урок 10: vacuum, заморозка и сборка мёртвых версий
- Своя СУБД на TS · урок 11: бинарный протокол и сервер
Workshop · СУБД на Effect
Изделие «Своя СУБД на Effect», крейт ourdb-effect
- Своя СУБД на Effect · урок 1: страницы и свой файловый слой
- Своя СУБД на Effect · урок 2: буферный пул
- Своя СУБД на Effect · урок 3: куча и записи
- Своя СУБД на Effect · урок 4: B+Tree индекс
- Своя СУБД на Effect · урок 5: свой SQL, лексер и парсер
- Своя СУБД на Effect · урок 6: анализ, план, исполнитель, EXPLAIN
- Своя СУБД на Effect · урок 7: журнал упреждающей записи и восстановление
- Своя СУБД на Effect · урок 8: транзакции, откат и видимость
- Своя СУБД на Effect · урок 9: конкуренция, блокировки и дедлоки
- Своя СУБД на Effect · урок 10: vacuum, заморозка и сборка мёртвых версий
- Своя СУБД на Effect · урок 11: бинарный протокол и сервер
Workshop · СУБД на Go
Изделие «Своя СУБД на Go», крейт ourdb
- Своя СУБД на Go · урок 1: страницы и свой файловый слой
- Своя СУБД на Go · урок 2: буферный пул
- Своя СУБД на Go · урок 3: куча и записи
- Своя СУБД на Go · урок 4: B+Tree индекс
- Своя СУБД на Go · урок 5: свой SQL, лексер и парсер
- Своя СУБД на Go · урок 6: анализ, план, исполнитель, EXPLAIN
- Своя СУБД на Go · урок 7: журнал упреждающей записи и восстановление
- Своя СУБД на Go · урок 8: транзакции, откат и видимость
- Своя СУБД на Go · урок 9: конкуренция, блокировки и дедлоки
- Своя СУБД на Go · урок 10: vacuum, заморозка и сборка мёртвых версий
- Своя СУБД на Go · урок 11: бинарный протокол и сервер
Workshop · СУБД на Rust
Изделие «Своя СУБД на Rust», крейт ourdb
- Своя СУБД на Rust · урок 1: страницы и свой файловый слой
- Своя СУБД на Rust · урок 2: буферный пул
- Своя СУБД на Rust · урок 3: куча и записи
- Своя СУБД на Rust · урок 4: B+Tree индекс
- Своя СУБД на Rust · урок 5: свой SQL, лексер и парсер
- Своя СУБД на Rust · урок 6: анализ, план, исполнитель, EXPLAIN
- Своя СУБД на Rust · урок 7: журнал упреждающей записи и восстановление
- Своя СУБД на Rust · урок 8: транзакции, откат и видимость
- Своя СУБД на Rust · урок 9: конкуренция, блокировки и дедлоки
- Своя СУБД на Rust · урок 10: vacuum, заморозка и сборка мёртвых версий
- Своя СУБД на Rust · урок 11: бинарный протокол и сервер
Workshop · СУБД на Haskell
Изделие «Своя СУБД на Haskell», крейт ourdb
- Своя СУБД на Haskell · урок 1: страницы и свой файловый слой
- Своя СУБД на Haskell · урок 2: буферный пул
- Своя СУБД на Haskell · урок 3: куча и записи
- Своя СУБД на Haskell · урок 4: B+Tree индекс
- Своя СУБД на Haskell · урок 5: свой SQL, лексер и парсер
- Своя СУБД на Haskell · урок 6: анализ, план, исполнитель, EXPLAIN
- Своя СУБД на Haskell · урок 7: журнал упреждающей записи и восстановление
- Своя СУБД на Haskell · урок 8: транзакции, откат и видимость
- Своя СУБД на Haskell · урок 9: конкуренция, блокировки и дедлоки
- Своя СУБД на Haskell · урок 10: vacuum, заморозка и сборка мёртвых версий
- Своя СУБД на Haskell · урок 11: бинарный протокол и сервер
Понятия курса
Понятия разобраны внутри уроков. Нажми на понятие, чтобы открыть урок, где оно объясняется.
Теория · введение
- Архитектура СУБД и независимость данныхТри уровня ANSI/SPARC, физическая и логическая независимость, путь запроса через компоненты СУБД.урок 3 · Архитектура СУБД и независимость данныхопираются: урок 17, урок 20
- Зачем нужны БД и СУБДПроблемы файлов, база данных против СУБД, что СУБД берёт на себя, декларативные запросы.урок 1 · Зачем нужны базы данных и СУБДопираются: урок 2
- Модели данныхИерархическая, сетевая, реляционная и документная модели, связь «многие ко многим».урок 2 · Модели данных: от иерархической до документнойопираются: урок 3, урок 4, урок 23
Теория · реляционная модель
- КлючиСуперключ, потенциальный, первичный, альтернативный и внешний ключи, суррогатные и естественные ключи.урок 5 · Ключи: потенциальные, первичные и внешниеопираются: урок 6, урок 10, урок 13
- Отношения, кортежи, атрибуты и доменыОтношение как множество кортежей, атрибуты и домены, степень и мощность, атомарность значений.урок 4 · Отношения, кортежи, атрибуты и доменыопираются: урок 5, урок 7
- NULL и целостностьNULL, трёхзначная логика, ловушки WHERE и NOT IN, ограничения целостности домена, сущности и ссылок.урок 6 · NULL, трёхзначная логика и целостность
Теория · реляционная алгебра
- Выборка, проекция и переименованиеЗамкнутость алгебры, σ как WHERE, π как SELECT DISTINCT, ρ как AS, сцепление операций.урок 7 · Выборка, проекция и переименованиеопираются: урок 8, урок 26
- Операции над множествами и произведениеОбъединение, пересечение, разность, совместимость по объединению, декартово произведение.урок 8 · Множественные операции и произведениеопираются: урок 9
- Соединения и делениеТета- и эквисоединение, естественное и внешние соединения, деление для вопросов со словом «все».урок 9 · Соединения и деление
Теория · ER-моделирование
- От ER-модели к таблицамПравила перевода: сущности, составные и многозначные атрибуты, связи 1:1, 1:N и M:N, обязательность как NOT NULL.урок 11 · От ER-модели к реляционной схемеопираются: урок 12
- Слабые сущностиВладелец, частичный ключ, идентифицирующая связь, составной и суррогатный ключ, ON DELETE CASCADE.урок 12 · Слабые сущности и идентификаторы
- Сущности, атрибуты и связиER-модель Чена, виды атрибутов, кратность и обязательность связей, нотация «воронья лапка».урок 10 · Сущности, атрибуты и связиопираются: урок 11
Теория · нормализация
- Аномалии и нормальные формы 1NF, 2NF, 3NFАномалии вставки, обновления и удаления, частичные и транзитивные зависимости, разложение без потерь.урок 15 · Аномалии и нормальные формы 1NF, 2NF, 3NFопираются: урок 16
- Замыкание атрибутов и поиск ключейАлгоритм X⁺, проверка следования зависимости, суперключи и потенциальные ключи через замыкание.урок 14 · Замыкание атрибутов и поиск ключейопираются: урок 15
- Функциональные зависимостиЗависимость X → Y, детерминант, тривиальные зависимости, аксиомы Армстронга и их следствия.урок 13 · Функциональные зависимости и аксиомы Армстронгаопираются: урок 14
- BCNF и денормализацияФорма Бойса-Кодда, сохранение зависимостей, счётчики, копии колонок и материализованные представления.урок 16 · BCNF и денормализация
Теория · транзакции
- Аномалии параллелизма и уровни изоляцииГрязное и неповторяемое чтение, фантомы, потерянное обновление, четыре уровня изоляции.урок 18 · Проблемы параллелизма и уровни изоляцииопираются: урок 19
- Блокировки, сериализуемость и восстановлениеСериализуемость, разделяемые и исключительные блокировки, двухфазная блокировка, дедлок, журнал и восстановление.урок 19 · Блокировки, сериализуемость и восстановление
- Транзакции и ACIDТранзакция как «всё или ничего», атомарность, согласованность, изоляция и долговечность.урок 17 · Транзакции и свойства ACIDопираются: урок 18
Теория · физический уровень
- Индексы: B-дерево и хешИндекс как указатель, B-дерево для равенства и диапазонов, хеш-индекс для равенства, цена индекса на запись.урок 21 · Индексы: B-дерево и хешопираются: урок 22
- План запроса и компромиссыОптимизатор, полный просмотр против индекса, селективность, EXPLAIN, компромиссы проектирования.урок 22 · План запроса и компромиссы проектирования
- Страницы и файлыСтраница как единица чтения, файлы таблиц, страница со слотами, буферный кэш.урок 20 · Как хранятся данные: страницы и файлыопираются: урок 21
Теория · современный ландшафт
- Модели NoSQLКлюч-значение, документы, колоночные и широкие колонки, графы: модель, сильный запрос, слабое место.урок 24 · Модели NoSQL: ключ-значение, документы, колонки, графыопираются: урок 25
- Ограничения реляционной модели и CAPМасштабирование, репликация и шардирование, теорема CAP и PACELC.урок 23 · Ограничения реляционной модели и теорема CAPопираются: урок 24
- NewSQL и выбор хранилищаРаспределённые SQL-базы и порядок выбора хранилища под задачу.урок 25 · NewSQL и выбор хранилища под задачу
SQL · основы выборки
- Порядок выполнения запросаЛогический порядок FROM, WHERE, GROUP BY, HAVING, SELECT, DISTINCT, ORDER BY, LIMIT и почему псевдоним не виден в WHERE.урок 26 · Порядок выполнения SQL-запросаопираются: урок 27
- DISTINCT и уникальность строкDISTINCT по всей строке, DISTINCT ON, DISTINCT против GROUP BY.урок 28 · DISTINCT и уникальность строкопираются: урок 29
- NULL и трёхзначная логикаСравнения с NULL, IS NULL, COALESCE, NULL в агрегатах и NOT IN.урок 29 · NULL и трёхзначная логикаопираются: урок 30
- ORDER BY и сортировкаСортировка по нескольким колонкам, NULLS FIRST и LAST, стабильность и пагинация.урок 30 · ORDER BY и сортировкаопираются: урок 31
- WHERE против HAVINGФильтр строк до группировки против фильтра групп после неё.урок 27 · WHERE против HAVINGопираются: урок 28
SQL · JOIN-ы
- Анти-джойныNOT EXISTS, NOT IN и LEFT JOIN IS NULL, ловушка NOT IN с NULL.урок 34 · Анти-джойны: NOT EXISTS, NOT IN, LEFT JOIN IS NULLопираются: урок 35
- Виды JOININNER, LEFT, RIGHT, FULL и CROSS JOIN на одной паре таблиц.урок 31 · Виды JOIN: INNER, LEFT, RIGHT, FULL, CROSSопираются: урок 32
- Дубликаты при джойнахРазмножение строк при соединении один ко многим и завышенные суммы.урок 35 · Дубликаты при джойнахопираются: урок 36
- СамосоединениеТаблица соединяется сама с собой: сотрудник и руководитель, пары строк.урок 33 · Самосоединение (self-join)опираются: урок 34
- LEFT JOIN: ON против WHEREУсловие на правую таблицу в WHERE превращает LEFT JOIN во внутренний.урок 32 · LEFT JOIN: условие в WHERE против ONопираются: урок 33
SQL · агрегация
- Найти X по группамМаксимум, минимум и строка с максимумом в каждой группе.урок 39 · Типичная задача: найти X по группамопираются: урок 40
- Условный подсчётАгрегаты с CASE и FILTER, сводные таблицы в одном запросе.урок 38 · Условный подсчёт: агрегаты с CASEопираются: урок 39
- COUNT(*), COUNT(col), COUNT(DISTINCT)Что считает каждый вариант COUNT и как NULL меняет ответ.урок 37 · COUNT(*) против COUNT(col) против COUNT(DISTINCT)опираются: урок 38
- GROUP BY и агрегатные функцииГруппировка, агрегаты, правило «в SELECT только группировка или агрегат».урок 36 · GROUP BY и агрегатные функцииопираются: урок 37
SQL · подзапросы и окна
- Вторая по величине зарплатаКлассическая задача четырьмя способами и ловушка с одинаковыми зарплатами.урок 44 · Классика: вторая по величине зарплатаопираются: урок 45
- ПодзапросыСкалярные, табличные и коррелированные подзапросы, EXISTS и IN.урок 40 · Подзапросы: скалярные и коррелированныеопираются: урок 41
- CTE и WITHИменованные подзапросы для читаемости, рекурсивный CTE для иерархии.урок 41 · CTE: конструкция WITH для читаемостиопираются: урок 42
- LAG, LEAD и SUM OVERСоседние строки и накопительные агрегаты в окне.урок 43 · Оконные функции: LAG, LEAD и SUM OVERопираются: урок 44
- ROW_NUMBER, RANK, DENSE_RANKОконные функции ранжирования и их поведение при равных значениях.урок 42 · Оконные функции: ROW_NUMBER, RANK, DENSE_RANKопираются: урок 43
SQL · классические задачи
- Дубликаты строкНайти повторы через GROUP BY HAVING и удалить, оставив по одной строке.урок 45 · Дубликаты строк: найти и удалитьопираются: урок 46
- Нарастающий итог и разница соседейSUM OVER с ORDER BY, рамка окна, LAG для разницы с предыдущей строкой.урок 47 · Нарастающий итог и разница соседних строкопираются: урок 48
- Пропуски и строки без парыПропуски в последовательности через generate_series и LEAD, клиенты без заказов.урок 48 · Пропуски в последовательности и пользователи без заказовопираются: урок 49
- Топ-N по группамПервые N строк в каждой группе через ROW_NUMBER и LATERAL.урок 46 · Топ-N по группамопираются: урок 47
SQL · производительность и проектирование
- Индексы на собеседованииКак индекс ускоряет поиск и когда не помогает: функции, LIKE, низкая селективность, порядок колонок.урок 49 · Индексы: как ускоряют и когда не работаютопираются: урок 50
- Нормализация против денормализацииКак отвечать про нормальные формы и когда денормализовать.урок 51 · Нормализация против денормализацииопираются: урок 52
- Проблема N+1 и EXPLAINN+1 запросов из ORM, как его увидеть и починить, чтение EXPLAIN.урок 50 · Проблема N+1 и EXPLAIN QUERY PLANопираются: урок 51
- Транзакции и ACID на собеседованииACID, уровни изоляции и типичные аномалии в формате ответа интервьюеру.урок 52 · Транзакции и ACID
Junior
- БД для кэшаRedis, Memcached, Valkey. In-memory, eviction policies, KV-в-RAM, persistence trade-offs.урок 53 · PostgreSQL и SQL с нуля · от psql до индексовопираются: урок 57
- Индексы: плюсы и минусыЗачем нужны, замедление write, размер, partial/unique/covering, выбор колонок.урок 53 · PostgreSQL и SQL с нуля · от psql до индексовопираются: урок 54
- СУБД и виды БДЧто такое СУБД, OLTP vs OLAP, реляционная, документная, KV, графовая, временная, search, vector.урок 53 · PostgreSQL и SQL с нуля · от psql до индексов
- PostgreSQL базовоРабота из CLI. Принцип СУБД. 1НФ/2НФ/3НФ. Концептуальная модель.урок 53 · PostgreSQL и SQL с нуля · от psql до индексов
- SQL: PostgreSQL диалектDDL/DML, типы, GROUP BY/HAVING/WHERE/UNION/JOIN, индексы, MAX/AVG/IN/ANY/ALL/EXISTS.урок 53 · PostgreSQL и SQL с нуля · от psql до индексовопираются: урок 54
Middle
- Продвинутый PostgreSQLХранимые процедуры, триггеры, блокировки, views, JSON/JSONB, arrays, транзакции.урок 54 · PostgreSQL Middle · транзакции, JSONB, блокировкиопираются: урок 55
- Теория БДSQL vs NoSQL. ACID. Денормализация. Уровни изоляции. Локи. K-V stores. MongoDB, Redis, Cache.урок 54 · PostgreSQL Middle · транзакции, JSONB, блокировкиопираются: урок 55
- Хранение вложенных объектовРеляционная нормализация vs JSONB vs отдельная коллекция. Индексы по JSONB.урок 54 · PostgreSQL Middle · транзакции, JSONB, блокировки
- Шардирование и репликацияГоризонтальное vs вертикальное шардирование, выбор ключа, hot keys, primary/replica, sync vs async.урок 55 · PostgreSQL Middle+ · EXPLAIN, шардинг, репликация
Middle+
- Поисковые системыElasticsearch/OpenSearch, Sphinx, Meilisearch, Typesense.урок 55 · PostgreSQL Middle+ · EXPLAIN, шардинг, репликация
- Теория распределённых БДCAP, B-trees, journaling, репликация, Raft/Paxos, антиэнтропия, two generals, CRDT, Tarantool, Kafka, ClickHouse.урок 55 · PostgreSQL Middle+ · EXPLAIN, шардинг, репликацияопираются: урок 56
- Углублённый PostgreSQLER, оконные функции, ранжирование, frames, CTE, RECURSIVE, JsonPath, GIN, EXPLAIN ANALYZE.урок 55 · PostgreSQL Middle+ · EXPLAIN, шардинг, репликацияопираются: урок 56, урок 57
Senior
- PostgreSQL deep-diveХранение на диске, конфиги, репликация (streaming/logical), multimaster, failover, шардинг, реляционная алгебра Кодда.урок 56 · PostgreSQL internals · MVCC, WAL, vacuum, pgbouncerопираются: урок 58
Спец-БД
- Redis: cache, queues, locks, streamsCache-aside, sessions, rate limit, pub/sub, leaderboards, Redlock, BullMQ, streams. Подводные камни.урок 57 · Redis и ClickHouse · спец-БД для кэша и аналитики
- ClickHouse: column-storeMergeTree, ReplacingMergeTree, ordering vs primary vs partition key, materialized views.урок 57 · Redis и ClickHouse · спец-БД для кэша и аналитикиопираются: урок 58
Внутренности
- MVCCxmin/xmax, snapshot isolation. Bloat, vacuum overhead, long-running tx. MVCC в Oracle/MySQL/SQLite/CockroachDB.урок 56 · PostgreSQL internals · MVCC, WAL, vacuum, pgbouncerопираются: урок 59, урок 66, урок 67, урок 77, урок 88, урок 99, урок 110
- PostgreSQL internalsPages 8K, TOAST, HOT updates, fill factor, dead tuples, VACUUM/ANALYZE, txid wraparound, индексы (B/Hash/GIN/GiST/SP-GiST/BRIN), WAL, checkpoints, pgbouncer.урок 56 · PostgreSQL internals · MVCC, WAL, vacuum, pgbouncerопираются: урок 59, урок 60, урок 61, урок 62, урок 65, урок 68, урок 70, урок 79, урок 81, урок 90, урок 92, урок 101, урок 103, урок 112
Архитектура данных
- OLTP vs OLAPRow vs column store. Postgres -> CDC -> ClickHouse pipeline. HTAP-системы.урок 58 · Архитектура данных · OLTP, OLAP, Lakehouse, CDC
- Data Lake / LakehouseIceberg/Delta/Hudi. Spark, Trino, DuckDB. Modern data stack.урок 58 · Архитектура данных · OLTP, OLAP, Lakehouse, CDC
- Streaming: CDC, Kafka, FlinkDebezium, Kafka guarantees, ordering, partition key. Streaming vs batch vs micro-batch.урок 58 · Архитектура данных · OLTP, OLAP, Lakehouse, CDC
Workshop · СУБД на TS
- Своя СУБД · анализ, план, исполнитель, EXPLAINУрок 6 воркшопа ourdb: верхняя половина движка. Каталог таблиц в памяти, binder (имена в индексы, проверка типов, трёхзначная логика NULL), планировщик с выбором метода доступа (seq scan против index scan, саргабельность, пересечение диапазонов), исполнитель по модели Volcano (open/next/close), EXPLAIN и встроенный движок. Без транзакций и MVCC, они в уроках 7, 8.урок 64 · Своя СУБД на TS · урок 6: анализ, план, исполнитель, EXPLAINопираются: урок 65
- Своя СУБД · бинарный протокол и серверУрок 11 воркшопа ourdb (capstone): движок в сети. Своё кадрирование (1 байт тип, 4 байта длина big-endian, payload) с разбором фрагментированного TCP-потока, simple query protocol (Query, RowDescription, DataRow, CommandComplete, ErrorResponse, ReadyForQuery), сессия на соединение со своей транзакцией, TCP-сервер и клиент. Клиент подключается, шлёт SQL, получает типизированные строки.урок 69 · Своя СУБД на TS · урок 11: бинарный протокол и сервер
- Своя СУБД · буферный пулУрок 2 воркшопа ourdb: кэш страниц между движком и диском, fetchPage/unpinPage, pin как защита от вытеснения, dirty-флаг, вытеснение по алгоритму clock (second-chance), hit rate.урок 60 · Своя СУБД на TS · урок 2: буферный пулопираются: урок 61
- Своя СУБД · журнал упреждающей записи и восстановлениеУрок 7 воркшопа ourdb: долговечность append-пути. Журнал упреждающей записи (WAL) с самоописывающими записями и CRC32, правило write-ahead через хук буферного пула, redo-восстановление вставок и DDL при старте, идемпотентность по page.lsn. Транзакций и удаления через версии ещё нет (autocommit), это следующий урок.урок 65 · Своя СУБД на TS · урок 7: журнал упреждающей записи и восстановлениеопираются: урок 66
- Своя СУБД · конкуренция, блокировки и дедлокиУрок 9 воркшопа ourdb: несколько транзакций одновременно. Snapshot isolation (читатели не блокируют писателей, непустой active в снимке), эксклюзивный лок строки и строгий 2PL, write-write конфликт через проверку xmax (SerializationError), детект дедлока обходом графа ожидания (DeadlockError) и LockWaitError на занятом ресурсе. Сборка мёртвых версий это следующий урок.урок 67 · Своя СУБД на TS · урок 9: конкуренция, блокировки и дедлокиопираются: урок 68, урок 69
- Своя СУБД · куча и записиУрок 3 воркшопа ourdb: таблица как куча страниц, кортеж и его сериализация по контракту (xmin/xmax, null bitmap), RID, вставка с поиском места, sequential scan, логическое удаление.урок 61 · Своя СУБД на TS · урок 3: куча и записиопираются: урок 62
- Своя СУБД · свой SQL, лексер и парсерУрок 5 воркшопа ourdb: фронтенд SQL как три чистые функции. Лексер режет строку на токены, парсер рекурсивного спуска плюс Pratt по таблице приоритетов собирает AST (размеченные объединения), pretty-printer печатает дерево обратно и проверяется round-trip, ошибки несут позицию со стрелкой.урок 63 · Своя СУБД на TS · урок 5: свой SQL, лексер и парсеропираются: урок 64
- Своя СУБД · страницы и файловый слойУрок 1 воркшопа ourdb: DiskManager как массив страниц поверх файла, slotted page, заголовок и слоты, little-endian, free space = upper - lower.урок 59 · Своя СУБД на TS · урок 1: страницы и свой файловый слойопираются: урок 60
- Своя СУБД · транзакции, откат и видимостьУрок 8 воркшопа ourdb: атомарность и MVCC-версии. Менеджер транзакций (xid, состояния, undo-лог, цепочка prev_lsn), BEGIN/COMMIT/ROLLBACK, версии кортежа через xmin/xmax, функция видимости isVisible по снимку и commit-status, MVCC-удаление через setXmax, commit- и checkpoint-aware recovery, no-steal через flushableLsn. Однопользовательский режим, конкуренция (блокировки, дедлоки) это следующий урок.урок 66 · Своя СУБД на TS · урок 8: транзакции, откат и видимостьопираются: урок 67
- Своя СУБД · B+Tree индексУрок 4 воркшопа ourdb: дисковый B+Tree поверх буферного пула, узел это страница (заголовок в special-области), точечный поиск за O(высоты), диапазонный скан по связанным листьям, вставка с расщеплением и подъёмом разделителя, корень в метастранице.урок 62 · Своя СУБД на TS · урок 4: B+Tree индексопираются: урок 63, урок 64
- Своя СУБД · vacuum, заморозка и сборка мёртвых версийУрок 10 воркшопа ourdb: уборка за MVCC. Vacuum находит мёртвые версии (вставки откатанных транзакций и удаления за горизонтом), уплотняет страницу с сохранением номеров слотов (RID стабилен), замораживает старые xmin от xid-wraparound. Горизонт удаляемости по xmin живых снимков. Дальше бинарный протокол и сервер.урок 68 · Своя СУБД на TS · урок 10: vacuum, заморозка и сборка мёртвых версийопираются: урок 69
Workshop · СУБД на Effect
- СУБД на Effect · анализ, план, исполнитель, EXPLAINУрок 6 Effect-трека ourdb: верхняя половина движка. Каталог, binder (резолв имён и типов), вычислитель с трёхзначной логикой, операторы Volcano, планировщик с выбором seq/index scan, EXPLAIN, встроенный движок. Эффект-грани: операторы это Stream (ленивые, финалайзеры вместо open/next/close) плюс Effect для DML, граница engineTry мостит брошенный EngineError в канал ошибок, каталог собирает ресурсы таблиц в Scope базы через Layer.build (нет db.close). switch вместо ts-pattern. Без транзакций/WAL/MVCC: ENGINE_XID фиксирован, DELETE физический.урок 75 · Своя СУБД на Effect · урок 6: анализ, план, исполнитель, EXPLAINопираются: урок 76
- СУБД на Effect · бинарный протокол и серверУрок 11 Effect-трека ourdb (capstone): сетевой протокол на @effect/platform. TCP-сервер и клиент через SocketServer/NodeSocket.makeNet (НЕ node:net), structured concurrency через Effect.forkScoped и Effect.ensuring. framing/messages чистые (как Page/Tuple/sql), session/server/client это Effect. WireError это Data.TaggedError, errorCode по error._tag (switch вместо instanceof-цепочки TS-трека). Ключевая идиома: closed-Deferred в client.end ждёт завершения цикла чтения, чтобы Terminate успел докатить откат транзакции на сервере (иначе следующий запрос ловит LockWaitError).урок 80 · Своя СУБД на Effect · урок 11: бинарный протокол и сервер
- СУБД на Effect · буферный пулУрок 2 Effect-трека ourdb: кэш страниц между движком и диском, но координация вынесена в тип. Пул это сервис Context.Tag и Layer.effect поверх DiskManager, общее изменяемое состояние под семафором на один пермит (Effect.makeSemaphore(1)), а не Ref/STM, потому что вытеснение делает ввод-вывод. Алгоритм clock дословно как в TS-треке. pin оформлен как withPin через Effect.acquireRelease: финалайзер снимает закрепление по выходу из scope.урок 71 · Своя СУБД на Effect · урок 2: буферный пулопираются: урок 72
- СУБД на Effect · конкуренция, блокировки и дедлокиУрок 9 Effect-трека ourdb: snapshot isolation на непустом active, эксклюзивный лок строки, строгий 2PL, write-write конфликт (first-updater-wins), детект дедлока через граф ожидания. LockManager на STM/TRef: три TRef (owners/held/waitsFor), copy-on-write Map/Set, acquire/release как STM-транзакции. db.begin становится Effect<Transaction>, хэндлы чередуются. Ключевая тонкость порта: STM не падает на конфликте (STM.fail откатил бы запись ребра ожидания), вместо этого возвращает дискриминант acquired/wait/deadlock, типизированную ошибку (LockWaitError/DeadlockError) накладываем Effect.flatMap на границе с явной аннотацией возврата.урок 78 · Своя СУБД на Effect · урок 9: конкуренция, блокировки и дедлокиопираются: урок 79, урок 80
- СУБД на Effect · куча и записиУрок 3 Effect-трека ourdb: таблица и запись, и граница Effect ровно по сущностям. Schema и Tuple чистые (сериализация по контракту байтов с null bitmap), поэтому совпадают с TS-треком без Effect. HeapFile вскрывает три грани Effect: seq scan это Stream (ленивый, постоянная память), точечное чтение readTuple это Option, доступ к странице через withPin из урока 2, кортеж больше страницы это HeapError в канале E. makeHeapFile это значение (таблиц много), но возвращает Effect, потому что зависит от BufferPool.урок 72 · Своя СУБД на Effect · урок 3: куча и записиопираются: урок 73
- СУБД на Effect · свой SQL, лексер и парсерУрок 5 Effect-трека ourdb: фронтенд SQL. Лексер, парсер рекурсивного спуска с Pratt-разбором выражений, pretty-printer, round-trip как доказательство. Граница Effect: разбор это чистые функции, но они могут не сложиться, поэтому без диска и ресурсов берём не Effect, а Either. Внутренний рекурсивный спуск бросает SqlError (Data.TaggedError) для управления потоком, а публичные tokenize/parse ловят бросок в Either через sqlEither. В уроке 6 движок поднимет этот Either в канал ошибок Effect через yield*.урок 74 · Своя СУБД на Effect · урок 5: свой SQL, лексер и парсеропираются: урок 75
- СУБД на Effect · страницы и файловый слойУрок 1 Effect-трека ourdb: тот же страничный слой, но безопасность ресурса вынесена в тип. DiskManager как сервис Context.Tag и Layer.scoped, файловый дескриптор через Effect.acquireRelease (финалайзер закрывает его при выходе из scope, в том числе при ошибке и interrupt), ошибки ввода-вывода как Data.TaggedError в канале E. Page остаётся чистой обёрткой над байтами.урок 70 · Своя СУБД на Effect · урок 1: страницы и свой файловый слойопираются: урок 71
- СУБД на Effect · транзакции, откат и видимостьУрок 8 Effect-трека ourdb (7b по TS): атомарность и MVCC. BEGIN/COMMIT/ROLLBACK, кортеж с версиями (xmin/xmax), MVCC-удаление через setXmax+logSetXmax, видимость через isVisible на снимке. Эффект-грани: TransactionManager со смешанной подписью (begin/logInsert/logSetXmax/flushableLsn синхронные, commit/abort это Effect), ApplyUndo как Effect-callback в abort, sessionXid в let-замыкании, runAutocommitDml через Effect.either с abort на Left, canFlush no-steal по-настоящему работает. Recovery двухпроходная commit-aware (фильтр по committed и хвост после checkpoint). Без конкуренции/локов (это урок 9).урок 77 · Своя СУБД на Effect · урок 8: транзакции, откат и видимостьопираются: урок 78
- СУБД на Effect · B+Tree индексУрок 4 Effect-трека ourdb: дисковый B+Tree поверх буферного пула, ключ i64 в RID за O(log n) страниц, диапазонный скан по связанным листьям. Узел это вид на страницу (BTreeNode чистый, как в TS). Главная грань Effect: форма рекурсии решает память. Вставка держит стек pin-ов (scope открыт сквозь рекурсию в ребёнка), чтение держит один pin (scope закрыт до рекурсии). rangeScan это Stream через paginateChunkEffect, search это Option, корень в Ref, битый файл это BTreeError.урок 73 · Своя СУБД на Effect · урок 4: B+Tree индексопираются: урок 74, урок 75
- СУБД на Effect · vacuum, заморозка и сборка мёртвых версийУрок 10 Effect-трека ourdb: vacuum поверх MVCC. Мёртвая версия (откатанная вставка или удаление за горизонтом), горизонт удаляемости RecentGlobalXmin как минимум xmin по живым снимкам, заморозка против xid-wraparound. Effect-нарратив: проход поверх пула это композиция трёх примитивов (withPin, markDirty, Effect.scoped); чистая classify без Effect (ни ресурсов, ни сбоев); onRemove это Effect-callback (BTree.delete живёт в Effect). Базовая линия УРЕЗАНА: без indexCleanup (BTree без delete) и без invalidateFreeSpaceMap (наивный скан места), оба в упражнения. db.vacuum это Effect<VacuumStats, ExecError>, требует пустых openXids.урок 79 · Своя СУБД на Effect · урок 10: vacuum, заморозка и сборка мёртвых версийопираются: урок 80
- СУБД на Effect · WAL и восстановлениеУрок 7 Effect-трека ourdb (7a по TS): журнал упреждающей записи и redo-восстановление. Autocommit-durability на чистом пути: INSERT и CREATE переживают убийство процесса. Эффект-грани: WAL это ещё один файловый ресурс под Scope (makeWal через acquireRelease) рядом с DiskManager, операции памяти (append/currentLsn) синхронные (зовёт синхронный хук пула), операции диска (flush/readAll) это Effect. FlushHooks возвращаются в BufferPool: beforeFlush это Effect (write-ahead через wal.flushUpTo), canFlush синхронный no-steal-гейт (тривиально true в 7a). Recovery как Effect (redo-all, без commit-фильтра, без SetXmax).урок 76 · Своя СУБД на Effect · урок 7: журнал упреждающей записи и восстановлениеопираются: урок 77
Workshop · СУБД на Go
- СУБД на Go · анализ, план, исполнитель, EXPLAINУрок 6 Go-трека ourdb: верхняя половина движка. Каталог, binder (имена в индексы колонок, проверка типов), вычислитель с трёхзначной логикой NULL, операторы Volcano за интерфейсом Operator (Open, Next), планировщик с выбором seq scan или index scan, EXPLAIN, Database под sync.RWMutex. Ошибки движка это *dberr.Error с SQLSTATE-подобным кодом.урок 86 · Своя СУБД на Go · урок 6: анализ, план, исполнитель, EXPLAINопираются: урок 87
- СУБД на Go · бинарный протокол и серверУрок 11 Go-трека ourdb (финал): пакет wire и sync.RWMutex вокруг engine.Database. Кадры big-endian, FrameReader с полным выражением среза для payload, закрытая сумма сообщений через интерфейс с неэкспортированным методом, курсор разбора с залипающей ошибкой. Session без сокетов, своя транзакция на соединение, 25P02 после ошибки. Server: net.Listen на порту 0, горутина на соединение, карта conns под sync.Mutex, честное завершение через sync.WaitGroup. Клиент с мьютексом на запрос-ответ, End ждёт закрытия сервером. go test -race на восьми параллельных клиентах.урок 91 · Своя СУБД на Go · урок 11: бинарный протокол и сервер
- СУБД на Go · буферный пулУрок 2 Go-трека ourdb: кэш страниц между движком и диском. Пул на фиксированное число кадров, вытеснение по clock (second-chance), pin/unpin и dirty, отложенный сброс. Таблица кадров под sync.Mutex, потому что SELECT-ы из разных горутин закрепляют страницы одновременно. Диск за маленьким интерфейсом Disk, который тест подменяет счётчиком обращений.урок 82 · Своя СУБД на Go · урок 2: буферный пулопираются: урок 83
- СУБД на Go · конкуренция, блокировки и дедлокиУрок 9 Go-трека ourdb: snapshot isolation на непустом Active, пакет lock со строгим 2PL, граф ожидания и поиск цикла. Честное решение порта: Acquire не усыпляет горутину, а сразу отдаёт 55P03 (паритет с тестами TS, а в финале единственный безопасный вариант, потому что захват идёт под эксклюзивным sync.RWMutex движка из урока 11). Коды 40001, 40P01, 55P03 из dberr, локи отпускаются в commit и abort.урок 89 · Своя СУБД на Go · урок 9: конкуренция, блокировки и дедлокиопираются: урок 90, урок 91
- СУБД на Go · куча и записиУрок 3 Go-трека ourdb: таблица как куча страниц. Схема и кортеж с сериализацией по контракту (xmin/xmax/infomask/nattrs, null bitmap, int64 LE, text с длиной u32), значение колонки как any с проверкой типа, RID как сравнимая структура, вставка по подсказке FSM, seq scan курсором Next() (Item, bool, error), логическое удаление слота.урок 83 · Своя СУБД на Go · урок 3: куча и записиопираются: урок 84
- СУБД на Go · свой SQL, лексер и парсерУрок 5 Go-трека ourdb: фронтенд SQL. Лексер режет строку на токены со смещением, AST это закрытые интерфейсы Expr и Statement с неэкспортируемым методом-маркером, парсер рекурсивного спуска с Pratt-разбором выражений, pretty-printer и round-trip как доказательство. Внутри парсер выходит из глубины через panic/recover, как go/parser, наружу отдаёт *sql.Error со смещением и стрелкой.урок 85 · Своя СУБД на Go · урок 5: свой SQL, лексер и парсеропираются: урок 86
- СУБД на Go · страницы и файловый слойУрок 1 Go-трека ourdb: тот же страничный слой, но байты разложены руками. Page это массив [8192]byte с методами поверх encoding/binary.LittleEndian, disk.Manager это *os.File с ReadAt/WriteAt по смещению id * page.Size, ошибки возвращаются явным значением error, неполное чтение тоже ошибка. Тесты на go test и t.TempDir().урок 81 · Своя СУБД на Go · урок 1: страницы и свой файловый слойопираются: урок 82
- СУБД на Go · транзакции, откат и видимостьУрок 8 Go-трека ourdb: MVCC и транзакции. Пакет txn: State на iota (Aborted это нулевое значение), CommitStatus с floor после checkpoint, Snapshot с картой Active (чтение из nil-карты безопасно), IsVisible в пять строк. txn.Manager реализует heap.Journal, ведёт prev_lsn и undo-log, откатывает через функцию-колбэк, без своего мьютекса. Сессионная транзакция SQL и программные хэндлы db.Begin(). MVCC-удаление MarkDeleted, двухпроходный recovery по COMMIT от checkpoint, ротация журнала Truncate плюс WriteAt, no-steal через CanFlush.урок 88 · Своя СУБД на Go · урок 8: транзакции, откат и видимостьопираются: урок 89
- СУБД на Go · B+Tree индексУрок 4 Go-трека ourdb: дисковый B+Tree поверх буферного пула, ключ int64 в RID за O(высоты) страниц, диапазонный скан по связанным листьям. Узел это значение-вид Node{P *page.Page} с методами над байтами страницы, заголовок узла в special-области. Обход через замыкание visit(id, fn), которое снимает pin в defer, вставка с расщеплением и подъёмом разделителя, корень в метастранице.урок 84 · Своя СУБД на Go · урок 4: B+Tree индексопираются: урок 85, урок 86
- СУБД на Go · vacuum, заморозка и сборка мёртвых версийУрок 10 Go-трека ourdb: пакет vacuum. Бит InfomaskXminFrozen и Tuple.Freeze на получателе-значении, проверка Frozen в IsVisible, VacuumHorizon, page.VacuumRewrite с сохранением номеров слотов (Data обязаны быть отдельными буферами). Ловушка defer: аргументы вычисляются сразу, поэтому UnpinPage с флагом changed идёт через замыкание. Чистка индекса через колбэк OnRemove входит в базовую линию, потому что B+Tree на Go умеет Delete с урока 4.урок 90 · Своя СУБД на Go · урок 10: vacuum, заморозка и сборка мёртвых версийопираются: урок 91
- СУБД на Go · WAL и восстановлениеУрок 7 Go-трека ourdb: журнал упреждающей записи и redo-восстановление. Пакет wal: запись с заголовком little-endian и CRC-32 IEEE (hash/crc32, тот же полином, что zlib у TS), Decode до первой рваной записи с validEnd, payload-кодеки с проверкой длины вместо паники. wal.Manager под своим sync.Mutex: дозапись в память, WriteAt по смещению (без O_APPEND, чтобы затереть рваный хвост), File.Sync. Пакет recovery с интерфейсом Deps против цикла импорта, идемпотентный redo по page.LSN.урок 87 · Своя СУБД на Go · урок 7: журнал упреждающей записи и восстановлениеопираются: урок 88
Workshop · СУБД на Rust
- СУБД на Rust · анализ, план, исполнитель, EXPLAINУрок 6 Rust-трека ourdb: верхняя половина движка. Каталог, binder (имена в индексы колонок, проверка типов), вычислитель с трёхзначной логикой NULL и checked-арифметикой i64, операторы Volcano как Box<dyn Operator> с next() и Drop вместо close, планировщик с выбором seq scan или index scan, EXPLAIN и встроенный Database.урок 97 · Своя СУБД на Rust · урок 6: анализ, план, исполнитель, EXPLAINопираются: урок 98
- СУБД на Rust · бинарный протокол и серверУрок 11 Rust-трека ourdb (финал): движок в сети на std::net. Кадры big-endian и FrameReader для фрагментированного потока, simple query protocol на enum-сообщениях, сессия со своей транзакцией соединения и SQLSTATE в ErrorResponse (ошибка COMMIT это ответ с неизвестным исходом), TcpListener на 127.0.0.1:0, поток на соединение, Database в Arc<Mutex<…>> и возврат базы из Server::close. Клиент Connection с типизированными строками.урок 102 · Своя СУБД на Rust · урок 11: бинарный протокол и сервер
- СУБД на Rust · буферный пулУрок 2 Rust-трека ourdb: кэш страниц между движком и диском с вытеснением по clock. Pin это владение: fetch_page отдаёт PageGuard, Drop снимает закрепление, забыть unpin нельзя. Байты страницы берутся коротким latch через guard.read()/guard.write(), запись помечает страницу грязной. Пул меняется через &self (RefCell внутри), поэтому его делят слои выше.урок 93 · Своя СУБД на Rust · урок 2: буферный пулопираются: урок 94
- СУБД на Rust · конкуренция, блокировки и дедлокиУрок 9 Rust-трека ourdb: snapshot isolation на непустом снимке, LockManager со строгим 2PL и поиском цикла в графе ожидания, write-write конфликт по xmax. Лок не ждёт: занятый ресурс это Error::LockWait с SQLSTATE 55P03, как NOWAIT в Postgres, потому что движок однопоточный (RefCell в пуле) и в сервере живёт под одним Mutex. Ошибки конкуренции как варианты enum Error с sqlstate(), WriteCtx с reborrow.урок 100 · Своя СУБД на Rust · урок 9: конкуренция, блокировки и дедлокиопираются: урок 101
- СУБД на Rust · куча и записиУрок 3 Rust-трека ourdb: таблица как куча страниц. Схема, значение колонки как enum Value, кортеж с сериализацией по контракту (xmin/xmax/infomask/nattrs, null bitmap, i64 LE, text с длиной u32) и разбором с проверкой границ, RID как Copy-структура, вставка по подсказке FSM, seq scan и логическое удаление слота.урок 94 · Своя СУБД на Rust · урок 3: куча и записиопираются: урок 95
- СУБД на Rust · свой SQL: лексер и парсерУрок 5 Rust-трека ourdb: фронтенд SQL как три чистые функции. Лексер режет строку на токены со смещением в символах, парсер рекурсивного спуска плюс Pratt по таблице приоритетов собирает AST из enum-ов с Box для рекурсии, pretty-printer печатает дерево обратно и проверяется round-trip, ошибка разбора это Error::Sql с позицией и стрелкой.урок 96 · Своя СУБД на Rust · урок 5: свой SQL, лексер и парсеропираются: урок 97
- СУБД на Rust · страницы и файловый слойУрок 1 Rust-трека ourdb: тот же страничный слой, байты разложены руками. Page это Box<[u8; 8192]> с полями заголовка через from_le_bytes/to_le_bytes по константным смещениям, DiskManager это std::fs::File с seek и read_exact/write_all по смещению id * PAGE_SIZE, ошибки это Result с одним enum Error и From<io::Error> под оператор ?.урок 92 · Своя СУБД на Rust · урок 1: страницы и свой файловый слойопираются: урок 93
- СУБД на Rust · транзакции, откат и видимостьУрок 8 Rust-трека ourdb: атомарность и MVCC. Версии через xmin/xmax, MVCC-удаление записью SET_XMAX, снимок и is_visible, CommitStatus с водяным знаком, TransactionManager с split() для раздельных заимствований журнала и статусов, abort с undo через замыкание FnMut, no-steal через Arc<AtomicU64>, checkpoint с ротацией журнала и commit-aware recovery.урок 99 · Своя СУБД на Rust · урок 8: транзакции, откат и видимостьопираются: урок 100
- СУБД на Rust · B+Tree индексУрок 4 Rust-трека ourdb: дисковый B+Tree поверх буферного пула. Узел это вид BTreeNode<P: Deref<Target = Page>> над страницей без своих данных, родитель держится запиненным через рекурсию, а latch его байтов берётся коротко. Точечный поиск, range scan по связанным листьям, вставка с расщеплением и подъёмом разделителя, корень в метастранице.урок 95 · Своя СУБД на Rust · урок 4: B+Tree индексопираются: урок 96, урок 97
- СУБД на Rust · vacuum и заморозкаУрок 10 Rust-трека ourdb: уборка за MVCC. Бит frozen в infomask, горизонт удаляемости через fold, перепись страницы со стабильными слотами, проход Vacuum<'a> как структура ссылок с enum Verdict и колбэком чистки индекса, read-latch в блоке до write-latch, сброс FSM, штамп page.lsn и checkpoint вместо журналирования vacuum.урок 101 · Своя СУБД на Rust · урок 10: vacuum, заморозка и сборка мёртвых версийопираются: урок 102
- СУБД на Rust · WAL и восстановлениеУрок 7 Rust-трека ourdb: журнал упреждающей записи и redo. Записи с самописным CRC-32 (таблица через const fn, без крейтов), WalManager с хвостом в памяти и долговечностью через File::sync_all, write-ahead через FlushHooks: Send в буферном пуле, журнал в Arc<Mutex<WalManager>>, RecoveryDeps у каталога и идемпотентный redo по page.lsn. Падение в тестах это drop базы без close.урок 98 · Своя СУБД на Rust · урок 7: журнал упреждающей записи и восстановлениеопираются: урок 99
Workshop · СУБД на Haskell
- СУБД на Haskell · анализ, план, исполнитель, EXPLAINУрок 6 Haskell-трека ourdb: верхняя половина движка. Binder и планировщик это чистые функции над видом каталога (функции Text -> Maybe TableMeta и Text -> Either DbError TableAccess), BoundExpr отдельным типом от AST, вычислитель с логикой Клини и quot, операторы Volcano как схема плюс Stream без close, выбор index scan по саргабельным конъюнктам с границами в Integer, EXPLAIN через тот же chooseAccess, Database как newtype над каталогом без журнала и транзакций. Честные отличия: Int64 с переполнением и проверка литерала в binder.урок 108 · Своя СУБД на Haskell · урок 6: анализ, план, исполнитель, EXPLAINопираются: урок 109
- СУБД на Haskell · бинарный протокол и серверУрок 11 Haskell-трека ourdb (финал серии): simple query protocol в духе Postgres целиком как обработчик байт. FrameReader это значение с pushChunk :: FrameReader -> ByteString -> ([Frame], FrameReader), кодеки чистые, ServerMsg параметризован типом строки, сессия со своей транзакцией и статусом I/T/E, trySync перебрасывает асинхронные исключения, feedServer тестируется без сокетов. network только в подбиблиотеке ourdb:net (поток на соединение, bracket, mask_), этап проверяет обработчик.урок 113 · Своя СУБД на Haskell · урок 11: бинарный протокол и сервер
- СУБД на Haskell · буферный пулУрок 2 Haskell-трека ourdb: кэш страниц с вытеснением по clock. Записи кадров неизменяемы и лежат в Seq за IORef, каждое изменение кадра это функция Frame -> Frame, таблица страниц на IntMap, страницы остаются общими изменяемыми буферами. Стрелка часов как хвостовая рекурсия с потолком в два круга, withPage на onException с флагом dirty из результата действия. Хуки журнала (write-ahead, no-steal) добавятся в уроках 7 и 8.урок 104 · Своя СУБД на Haskell · урок 2: буферный пулопираются: урок 105
- СУБД на Haskell · конкуренция, блокировки и дедлокиУрок 9 Haskell-трека ourdb: snapshot isolation на непустом active, эксклюзивный лок строки и строгий 2PL, first-updater-wins через xmax, детект дедлока обходом графа ожидания. Переходы менеджера блокировок это чистые функции LockState -> (Either DbError (), LockState), граница одна STM-транзакция через stateTVar; конфликт возвращается значением, потому что throwSTM откатил бы ребро ожидания. Честный паритет с эталоном: LockWaitError вместо ожидания и один мьютекс перед Database.урок 111 · Своя СУБД на Haskell · урок 9: конкуренция, блокировки и дедлокиопираются: урок 112, урок 113
- СУБД на Haskell · куча и записиУрок 3 Haskell-трека ourdb: таблица как куча страниц. Своя монада Get над ByteString с проверкой границ и Builder для записи, порядок байтов как направление свёртки. Schema, Value и Tuple это алгебраические типы, serializeTuple и deserializeTuple чистые и возвращают Either DbError, null bitmap через setBit/testBit. HeapFile с ленивой картой свободного места в IORef, разбор страницы по снимку после короткого pin, seq scan как свой ленивый Stream в IO.урок 105 · Своя СУБД на Haskell · урок 3: куча и записиопираются: урок 106
- СУБД на Haskell · свой SQL: лексер и парсерУрок 5 Haskell-трека ourdb: фронтенд SQL как чистые функции с результатом Either DbError. Лексер сопоставляет образцы по списку символов (заглядывание вперёд образцом), AST это алгебраические типы с deriving Eq, парсер это монада над списком токенов с примитивами check/match/expect, выражения Pratt-разбором по общей с принтером таблице precedence, pretty-printer с приоритетными скобками и round-trip, ошибки со стрелкой. Смещения в символах Unicode.урок 107 · Своя СУБД на Haskell · урок 5: свой SQL, лексер и парсеропираются: урок 108
- СУБД на Haskell · страницы и файловый слойУрок 1 Haskell-трека ourdb: тот же страничный слой на boot-пакетах GHC. Page это newtype над ForeignPtr Word8 со скрытым конструктором и проверкой границ на каждом чтении и записи, числа little-endian собираются через Data.Bits, снимок pageBytes отдаёт неизменяемый ByteString для чистых кодеков. DiskManager это Handle без буфера с hGetBuf/hPutBuf прямо в страницу, fsync через FFI, явный счётчик чтений вместо шпиона. Ошибки одним типом DbError, шов liftEither. Честное отличие: openUnlocked снимает блокировку GHC «один писатель на файл».урок 103 · Своя СУБД на Haskell · урок 1: страницы и свой файловый слойопираются: урок 104
- СУБД на Haskell · транзакции, откат и видимостьУрок 8 Haskell-трека ourdb: BEGIN/COMMIT/ROLLBACK, версии через xmin/xmax, MVCC-удаление через setXmax. Видимость и CommitStatus с водяным знаком это чистые функции над неизменяемыми значениями. Состояние менеджера транзакций это неизменяемая запись в TVar, каждый переход одна STM-транзакция, а запись в WAL идёт снаружи STM (тип не пускает IO внутрь). Undo-лог данными, commit-aware recovery, no-steal через flushableLsn, checkpoint с ротацией журнала.урок 110 · Своя СУБД на Haskell · урок 8: транзакции, откат и видимостьопираются: урок 111
- СУБД на Haskell · B+Tree индексУрок 4 Haskell-трека ourdb: дисковый B+Tree поверх пула. Узел это набор функций над Page без своего типа, один бинарный поиск searchBy обслуживает lowerBound, route и routeLeftmost. Поиск отпускает pin до спуска (шаг как Either), вставка держит путь запиненным и возвращает расщепление значением Maybe (разделитель, правая страница), range scan это Stream пачками по листу, удаление с borrow, merge и схлопыванием корня, validate проверяет инварианты.урок 106 · Своя СУБД на Haskell · урок 4: B+Tree индексопираются: урок 107, урок 108
- СУБД на Haskell · vacuum, заморозка и сборка мёртвых версийУрок 10 Haskell-трека ourdb: vacuum поверх MVCC. Вердикт версии это чистая функция classify в тип-сумму Remove | Freeze | Keep, порядок охранных выражений это порядок правил. Бит frozen в infomask против xid-wraparound, горизонт по xmin живых снимков, перепись страницы одним vacuumRewrite со стабильными RID, чистка индекса колбэком, статистика свёрткой. Не журналируется: checkpoint после прохода и штамп page.lsn.урок 112 · Своя СУБД на Haskell · урок 10: vacuum, заморозка и сборка мёртвых версийопираются: урок 113
- СУБД на Haskell · WAL и восстановлениеУрок 7 Haskell-трека ourdb: журнал упреждающей записи и redo-восстановление в autocommit. CRC-32 руками поверх ByteString (таблица как CAF в строгом ByteString, BS.foldl'), потому что основная библиотека собирается только из boot-пакетов GHC. Кодек записи чистый (Builder, Get), WalManager держит Handle и IORef-ы, fsync(2) через FFI поверх hFlush. Write-ahead через FlushHooks пула, журнал кучи как запись функций, redo идемпотентен по page.lsn.урок 109 · Своя СУБД на Haskell · урок 7: журнал упреждающей записи и восстановлениеопираются: урок 110