Развернутый сценарий учебного занятия (Конспект)

Тема 4. Проектирование структур баз данных — Практическое занятие №10: управление проектом, этап 2

Полный преподавательский сценарий с прямой речью для регламентов 80 минут (основной) и 60 минут (сокращенный).

Дисциплина: ОП.08 Основы проектирования баз данных
Образовательная организация: СИЭУиП
Семестр и занятие: 4-й семестр, Занятие №28
Хронометраж: 80 мин (осн.) / 60 мин (сокр.)

Этап 1. Организационный момент и проблемная мотивация 80 мин: 5 мин (00:00–00:05) | 60 мин: 4 мин (00:00–00:04)

Прямая речь преподавателя:
«Здравствуйте, коллеги! Садитесь. Проверим явку и готовность рабочих станций. На прошлом занятии мы с вами собрали исполняемый файл клиентского проекта и убедились, что приложение может корректно подключаться к реляционной базе данных, проходить аутентификацию и выполнять запросы.

Но представьте типичную ситуацию из жизни крупной IT-компании: вечер пятницы, сервис интернет-магазина с десятками тысяч активных покупателей. Ведущему разработчику срочно понадобилось добавить учет скидочных купонов. Он открывает pgAdmin на рабочем компьютере, подключается напрямую к боевому серверу и выполняет команду: ALTER TABLE orders ADD COLUMN promo_code VARCHAR(20) NOT NULL;.

И в эту же секунду мобильное приложение и веб-сайт начинают выдавать ошибку 500 всем пользователям сервиса, а мониторинг заливается красным цветом. Как вы думаете, почему такая, казалось бы, безобидная команда положила промышленный сервис?»
Ожидаемые ответы студентов:
— «Потому что колонка создана с ограничением NOT NULL, а дефолтное значение разработчик не указал!»
— «Старое приложение при создании заказа не знает про новую колонку promo_code и не отправляет ее при INSERT, поэтому база отклоняет запрос!»
— «Команда ALTER TABLE на большой таблице заблокировала всю таблицу на запись!»
Прямая речь преподавателя:
«Абсолютно верно! Вы назвали сразу две фундаментальные проблемы: во-первых, нарушение обратной совместимости, а во-вторых, блокировку таблицы. Править структуру базы данных вручную через графические клиенты на живом сервере — это профессиональное преступление, так называемый ClickOps.

Сегодня на практическом занятии №10 мы освоим ключевой стандарт современной промышленной инженерии — Database as Code (DbaC). Мы изучим, как версионировать структуру базы данных с помощью миграций Flyway, как гарантировать обратную совместимость с помощью паттерна Expand/Contract и как проводить обязательное регрессионное тестирование клиентского приложения после любых DDL-изменений. Запишите тему занятия: Практическое занятие №10: управление проектом, этап 2.»

Этап 2. Актуализация опорных знаний и теоретический экскурс 80 мин: 15 мин (00:05–00:20) | 60 мин: 12 мин (00:04–00:16)

Преподаватель переключает экран на слайд 2 презентации и последовательно разбирает фундаментальные концепции эволюции схемы БД.
Прямая речь преподавателя:
«В отличие от обычного кода на C# или Java, базу данных нельзя просто пересобрать из Git. В ней хранятся терабайты живых данных клиентов. Поэтому изменения схемы должны накатываться шаг за шагом в виде версионированных миграций.

В мире существует два главных отраслевых стандарта: Flyway и Liquibase. Liquibase описывает изменения в XML или YAML, что удобно, если один проект должен работать и на PostgreSQL, и на Oracle, и на MySQL. Но абсолютное большинство команд выбирает Flyway — он работает на чистом SQL, предельно нагляден и дает полный контроль над возможностями вашей СУБД.

Посмотрите на слайд 4. Во Flyway действует строжайшее соглашение об именовании файлов:
  • V{Версия}__{Описание}.sql — версионированная миграция наката (например, V1__baseline.sql, V2__add_index.sql). Обратите внимание: между версией и описанием стоят СТРОГО два символа подчеркивания!
  • U{Версия}__{Описание}.sql — Undo-скрипт отката назад.
  • R__{Описание}.sql — повторяемая миграция для представлений (VIEW) и функций.
А как СУБД понимает, какие скрипты уже выполнялись, а какие еще нет? Обратите внимание на слайд 5: Flyway создает специальную системную таблицу flyway_schema_history.»
Прямая речь преподавателя:
«В этой таблице ключевую роль играет колонка checksum — это контрольная сумма файла миграции. Если разработчик применил миграцию V2 на тестовом сервере, а потом тихонько залез в файл и исправил там строчку, контрольная сумма изменится. При следующем запуске Flyway выдаст фатальную ошибку: Migration checksum mismatch и остановит деплой!

Запомните базовое правило релиз-инженера: файлы примененных миграций неизменяемы (immutable). Если вы ошиблись в V2 — вы не трогаете V2, а создаете новую миграцию V3__fix_column.sql.

Теперь взгляните на слайд 8: паттерн Expand/Contract (расширение-сжатие). Если вы хотите переименовать колонку или разделить таблицу без остановки сервиса (Zero-Downtime), вы никогда не делаете это в одну миграцию:
  1. Сначала Expand: создаете новую структуру параллельно со старой;
  2. Затем Transition: новое приложение пишет и в старую, и в новую колонку одновременно, а фоновый скрипт переносит историю;
  3. Затем переключаете чтение на новую структуру;
  4. И только в следующем релизе — Contract: удаляете старую колонку. Все клиенты продолжают работать без секунды простоя!»

Этап 3. Демонстрация сквозного эталона преподавателем 80 мин: 10 мин (00:20–00:30) | 60 мин: 8 мин (00:16–00:24)

Преподаватель открывает терминал и демонстрационную СУБД, демонстрируя пошаговый цикл наката, валидации и отката.
Прямая речь преподавателя:
«Внимание на экран. У нас есть чистая база данных. В папке migrations лежит файл V1__baseline_tables.sql. Мы запускаем мигратор. Смотрим в консоль СУБД:
SELECT installed_rank, version, description, checksum, success FROM flyway_schema_history;
Появилась строка: rank 1, version '1', success TRUE.

Теперь мы добавляем новую функциональность: создаем файл V2__add_loyalty_system.sql. Запускаем накат. Версия 2 успешно применилась. А теперь смоделируем аварийную ситуацию: релиз признан неудачным, нам нужно вернуть схему назад. Мы применяем зеркальный скрипт U2__drop_loyalty_system.sql.

Обратите внимание на правило LIFO (Last In, First Out): в прямом скрипте мы сначала создавали таблицу, а затем вешали внешний ключ. Значит, в скрипте отката мы обязаны СНАЧАЛА удалить внешний ключ, и только ПОТОМ удалять таблицу! Иначе СУБД вернет ошибку нарушения ограничений целостности.»

Этап 4. Самостоятельная практическая работа в zanyatie.html 80 мин: 40 мин (00:30–00:70) | 60 мин: 30 мин (00:24–00:54)

Прямая речь преподавателя:
«Переходим к выполнению практической части. Откройте в браузере интерактивный рабочий лист zanyatie.html.
Обязательно заполните свои настоящие фамилию, имя и номер учебной группы в шапке листа.

Я распределяю варианты по рядам и номерам компьютеров:
  • Вариант 1 (Складской комплекс): разработка миграции V2 по добавлению уникального штрихкода EAN-13 в таблицу Товары и регрессионный тест старых форм складского поиска.
  • Вариант 2 (Гостиничный сервис): миграция V3 по выделению справочника источников бронирования и внешнего ключа в Бронированиях, проверка стабильности регистрации гостей.
  • Вариант 3 (Банковский портал): миграция V4 по выносу паспортов из таблицы клиентов с миграцией данных и написанием честного Undo-скрипта.
  • Вариант 4 (Образовательный портал): миграция V5 по добавлению составного индекса и анализ регрессионного времени формирования ведомостей.
В каждом варианте вам необходимо: написать прямой DDL-скрипт, написать зеркальный Undo-скрипт, рассчитать строку для таблицы истории версий, разработать регрессионный тест и ответить на 3 контрольных вопроса. Время пошло!»
Во время самостоятельной работы преподаватель обходит аудиторию, контролирует ход решения, обращает внимание студентов на использование дефолтных значений в NOT NULL колонках и сохранность связей.

Этап 5. Подведение итогов, разбор ошибок, рефлексия и ДЗ 80 мин: 10 мин (00:70–00:80) | 60 мин: 6 мин (00:54–00:60)

Прямая речь преподавателя:
«Остановите работу, сохраните данные в рабочих листах кнопкой «Сохранить ответы». Давайте разберем три главные ошибки, которые я заметил во время обхода аудитории:

1. В Варианте 1 несколько человек написали: ALTER TABLE goods ADD COLUMN barcode_ean13 VARCHAR(13) NOT NULL UNIQUE; без значения DEFAULT. Если в таблице уже лежат 5000 товаров, СУБД моментально упадет с ошибкой, потому что для старых записей значение не определено! Правильный путь: добавлять колонку либо с временным DEFAULT, либо делать поле NULLable, заполнять штрихкоды и только потом накладывать NOT NULL.

2. В Варианте 3 при откате Undo-скриптом была удалена таблица паспортов до того, как перенесенные данные вернулись в таблицу клиентов. Это приводит к безвозвратной потере информации!

Взгляните на слайд 15 презентации — знаменитый комикс xkcd про Маленького Бобби Таблицу. Мама назвала сына Robert'); DROP TABLE Students; --. Это классическое напоминание: любые манипуляции со схемой и данными должны быть изолированными, контролируемыми и защищенными.

Итоги и оценивание: работы оцениваются по 4-балльной рубрике. Ваши файлы сохранены в LocalStorage, нажмите кнопку «Экспорт в PDF» и сдайте готовые протоколы в систему контроля.
Для тех, кто отсутствовал или желает повысить оценку, в папке доступно резервное дистанционное задание domashnee_zadanie.html. Срок сдачи — до следующего занятия. Всем спасибо за работу, пара окончена!»