раздел 10

Databases

СУБД из CLI, ACID, индексы и EXPLAIN, MVCC и WAL, Redis и ClickHouse, CDC и lakehouse. От psql до архитектуры данных.

113 уроков127 тем · 26 кластеров

Начать раздел
Хочу пройти

Без входа у каждого урока видно начало. Войди, чтобы читать целиком, отмечать пройденное и решать задачи. войти

Мастерская: Своя СУБД на TS

этапов 0 из 11

Мастерская: Своя СУБД на Effect

этапов 0 из 11

Мастерская: Своя СУБД на Go

этапов 0 из 11

Мастерская: Своя СУБД на Rust

этапов 0 из 11

Мастерская: Своя СУБД на Haskell

этапов 0 из 11

Уроки раздела

Теория · введение

  1. Зачем нужны базы данных и СУБДJ~15 мин
  2. Модели данных: от иерархической до документнойJ~15 мин
  3. Архитектура СУБД и независимость данныхJ~15 мин

Теория · реляционная модель

  1. Отношения, кортежи, атрибуты и доменыJ~15 мин
  2. Ключи: потенциальные, первичные и внешниеJ~15 мин
  3. NULL, трёхзначная логика и целостностьJ~15 мин

Теория · реляционная алгебра

  1. Выборка, проекция и переименованиеJ~15 мин
  2. Множественные операции и произведениеJ~20 мин
  3. Соединения и делениеJ~20 мин

Теория · ER-моделирование

  1. Сущности, атрибуты и связиJ~15 мин
  2. От ER-модели к реляционной схемеJ~20 мин
  3. Слабые сущности и идентификаторыJ~15 мин

Теория · нормализация

  1. Функциональные зависимости и аксиомы АрмстронгаJ~10 мин
  2. Замыкание атрибутов и поиск ключейJ~10 мин
  3. Аномалии и нормальные формы 1NF, 2NF, 3NFJ~15 мин
  4. BCNF и денормализацияJ~15 мин

Теория · транзакции

  1. Транзакции и свойства ACIDJ~15 мин
  2. Проблемы параллелизма и уровни изоляцииJ~15 мин
  3. Блокировки, сериализуемость и восстановлениеJ~15 мин

Теория · физический уровень

  1. Как хранятся данные: страницы и файлыJ~15 мин
  2. Индексы: B-дерево и хешJ~15 мин
  3. План запроса и компромиссы проектированияJ~15 мин

Теория · современный ландшафт

  1. Ограничения реляционной модели и теорема CAPJ~10 мин
  2. Модели NoSQL: ключ-значение, документы, колонки, графыJ~15 мин
  3. NewSQL и выбор хранилища под задачуJ~15 мин

SQL · основы выборки

  1. Порядок выполнения SQL-запросаJ~20 мин
  2. WHERE против HAVINGJ~15 мин
  3. DISTINCT и уникальность строкJ~15 мин
  4. NULL и трёхзначная логикаJ~15 мин
  5. ORDER BY и сортировкаJ~15 мин

SQL · JOIN-ы

  1. Виды JOIN: INNER, LEFT, RIGHT, FULL, CROSSJ~15 мин
  2. LEFT JOIN: условие в WHERE против ONJ~15 мин
  3. Самосоединение (self-join)J~15 мин
  4. Анти-джойны: NOT EXISTS, NOT IN, LEFT JOIN IS NULLJ~15 мин
  5. Дубликаты при джойнахJ~20 мин

SQL · агрегация

  1. GROUP BY и агрегатные функцииJ~15 мин
  2. COUNT(*) против COUNT(col) против COUNT(DISTINCT)J~15 мин
  3. Условный подсчёт: агрегаты с CASEJ~15 мин
  4. Типичная задача: найти X по группамJ~15 мин

SQL · подзапросы и окна

  1. Подзапросы: скалярные и коррелированныеJ~15 мин
  2. CTE: конструкция WITH для читаемостиJ~15 мин
  3. Оконные функции: ROW_NUMBER, RANK, DENSE_RANKJ~15 мин
  4. Оконные функции: LAG, LEAD и SUM OVERJ~15 мин
  5. Классика: вторая по величине зарплатаJ~15 мин

SQL · классические задачи

  1. Дубликаты строк: найти и удалитьJ~20 мин
  2. Топ-N по группамJ~15 мин
  3. Нарастающий итог и разница соседних строкJ~20 мин
  4. Пропуски в последовательности и пользователи без заказовJ~20 мин

SQL · производительность и проектирование

  1. Индексы: как ускоряют и когда не работаютJ~20 мин
  2. Проблема N+1 и EXPLAIN QUERY PLANJ~20 мин
  3. Нормализация против денормализацииJ~15 мин
  4. Транзакции и ACIDJ~15 мин

Junior

  1. PostgreSQL и SQL с нуля · от psql до индексовJ~60 мин

Middle

  1. PostgreSQL Middle · транзакции, JSONB, блокировкиM~70 мин
  2. PostgreSQL Middle+ · EXPLAIN, шардинг, репликацияMS~110 мин

Внутренности

  1. PostgreSQL internals · MVCC, WAL, vacuum, pgbouncerS~110 мин

Спец-БД

  1. Redis и ClickHouse · спец-БД для кэша и аналитикиMS~100 мин

Архитектура данных

  1. Архитектура данных · OLTP, OLAP, Lakehouse, CDCS~80 мин

Workshop · СУБД на TS

Изделие «Своя СУБД на TS», крейт ourdb

  1. Своя СУБД на TS · урок 1: страницы и свой файловый слойS~70 мин
  2. Своя СУБД на TS · урок 2: буферный пулS~80 мин
  3. Своя СУБД на TS · урок 3: куча и записиS~90 мин
  4. Своя СУБД на TS · урок 4: B+Tree индексS~120 мин
  5. Своя СУБД на TS · урок 5: свой SQL, лексер и парсерS~150 мин
  6. Своя СУБД на TS · урок 6: анализ, план, исполнитель, EXPLAINS~230 мин
  7. Своя СУБД на TS · урок 7: журнал упреждающей записи и восстановлениеS~100 мин
  8. Своя СУБД на TS · урок 8: транзакции, откат и видимостьS~130 мин
  9. Своя СУБД на TS · урок 9: конкуренция, блокировки и дедлокиS~90 мин
  10. Своя СУБД на TS · урок 10: vacuum, заморозка и сборка мёртвых версийS~80 мин
  11. Своя СУБД на TS · урок 11: бинарный протокол и серверS~130 мин

Workshop · СУБД на Effect

Изделие «Своя СУБД на Effect», крейт ourdb-effect

  1. Своя СУБД на Effect · урок 1: страницы и свой файловый слойS~80 мин
  2. Своя СУБД на Effect · урок 2: буферный пулS~100 мин
  3. Своя СУБД на Effect · урок 3: куча и записиS~100 мин
  4. Своя СУБД на Effect · урок 4: B+Tree индексS~140 мин
  5. Своя СУБД на Effect · урок 5: свой SQL, лексер и парсерS~160 мин
  6. Своя СУБД на Effect · урок 6: анализ, план, исполнитель, EXPLAINS~200 мин
  7. Своя СУБД на Effect · урок 7: журнал упреждающей записи и восстановлениеS~110 мин
  8. Своя СУБД на Effect · урок 8: транзакции, откат и видимостьS~130 мин
  9. Своя СУБД на Effect · урок 9: конкуренция, блокировки и дедлокиS~110 мин
  10. Своя СУБД на Effect · урок 10: vacuum, заморозка и сборка мёртвых версийS~90 мин
  11. Своя СУБД на Effect · урок 11: бинарный протокол и серверS~140 мин

Workshop · СУБД на Go

Изделие «Своя СУБД на Go», крейт ourdb

  1. Своя СУБД на Go · урок 1: страницы и свой файловый слойS~90 мин
  2. Своя СУБД на Go · урок 2: буферный пулS~100 мин
  3. Своя СУБД на Go · урок 3: куча и записиS~130 мин
  4. Своя СУБД на Go · урок 4: B+Tree индексS~150 мин
  5. Своя СУБД на Go · урок 5: свой SQL, лексер и парсерS~170 мин
  6. Своя СУБД на Go · урок 6: анализ, план, исполнитель, EXPLAINS~240 мин
  7. Своя СУБД на Go · урок 7: журнал упреждающей записи и восстановлениеS~100 мин
  8. Своя СУБД на Go · урок 8: транзакции, откат и видимостьS~100 мин
  9. Своя СУБД на Go · урок 9: конкуренция, блокировки и дедлокиS~70 мин
  10. Своя СУБД на Go · урок 10: vacuum, заморозка и сборка мёртвых версийS~70 мин
  11. Своя СУБД на Go · урок 11: бинарный протокол и серверS~110 мин

Workshop · СУБД на Rust

Изделие «Своя СУБД на Rust», крейт ourdb

  1. Своя СУБД на Rust · урок 1: страницы и свой файловый слойS~110 мин
  2. Своя СУБД на Rust · урок 2: буферный пулS~100 мин
  3. Своя СУБД на Rust · урок 3: куча и записиS~120 мин
  4. Своя СУБД на Rust · урок 4: B+Tree индексS~160 мин
  5. Своя СУБД на Rust · урок 5: свой SQL, лексер и парсерS~190 мин
  6. Своя СУБД на Rust · урок 6: анализ, план, исполнитель, EXPLAINS~210 мин
  7. Своя СУБД на Rust · урок 7: журнал упреждающей записи и восстановлениеS~100 мин
  8. Своя СУБД на Rust · урок 8: транзакции, откат и видимостьS~110 мин
  9. Своя СУБД на Rust · урок 9: конкуренция, блокировки и дедлокиS~70 мин
  10. Своя СУБД на Rust · урок 10: vacuum, заморозка и сборка мёртвых версийS~70 мин
  11. Своя СУБД на Rust · урок 11: бинарный протокол и серверS~110 мин

Workshop · СУБД на Haskell

Изделие «Своя СУБД на Haskell», крейт ourdb

  1. Своя СУБД на Haskell · урок 1: страницы и свой файловый слойS~100 мин
  2. Своя СУБД на Haskell · урок 2: буферный пулS~60 мин
  3. Своя СУБД на Haskell · урок 3: куча и записиS~90 мин
  4. Своя СУБД на Haskell · урок 4: B+Tree индексS~100 мин
  5. Своя СУБД на Haskell · урок 5: свой SQL, лексер и парсерS~100 мин
  6. Своя СУБД на Haskell · урок 6: анализ, план, исполнитель, EXPLAINS~120 мин
  7. Своя СУБД на Haskell · урок 7: журнал упреждающей записи и восстановлениеS~90 мин
  8. Своя СУБД на Haskell · урок 8: транзакции, откат и видимостьS~100 мин
  9. Своя СУБД на Haskell · урок 9: конкуренция, блокировки и дедлокиS~80 мин
  10. Своя СУБД на Haskell · урок 10: vacuum, заморозка и сборка мёртвых версийS~60 мин
  11. Своя СУБД на Haskell · урок 11: бинарный протокол и серверS~110 мин

Понятия курса

Понятия разобраны внутри уроков. Нажми на понятие, чтобы открыть урок, где оно объясняется.

Теория · введение

Теория · реляционная модель

Теория · реляционная алгебра

Теория · ER-моделирование

Теория · нормализация

Теория · транзакции

Теория · физический уровень

Теория · современный ландшафт

SQL · основы выборки

SQL · JOIN-ы

SQL · агрегация

SQL · подзапросы и окна

SQL · классические задачи

SQL · производительность и проектирование

Junior

Middle

Middle+

Senior

Спец-БД

Внутренности

Архитектура данных

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