Самоучитель: PHP 8.5: инженерный практикум
Глава 17 из 22V. Хранение и время125 минут

Глава 17. Реляционная модель, PDO и транзакционная граница

Схема защищает факты независимо от маршрута записи, PDO отделяет значения от SQL, а транзакция охватывает целый прикладной исход.

После главы вы сможете
  • нарисовать отношения
  • выполнить параметризованный запрос
  • разместить транзакцию вокруг use case

Таблица хранит один вид факта

users, workouts, exercises и workout_sets имеют разные идентичности и сроки жизни. Внешний ключ связывает подход с тренировкой, CHECK ограничивает положительные повторения, UNIQUE фиксирует предметную уникальность. Ограничение базы дополняет валидацию приложения.

Не храните массив подходов сериализованной строкой только ради быстрого старта: запросы, ограничения и частичное обновление станут сложнее. JSON уместен для действительно документного необязательного фрагмента с ясной политикой индексации.

Схема сценария

Атомарная публикацияЕсли проверка версии или вставка истории не проходит, rollback отменяет весь предметный переход.BEGINuse caseUPDATEworkoutINSERThistoryCHECKaffected rowsCOMMITone fact
Если проверка версии или вставка истории не проходит, rollback отменяет весь предметный переход.

SQLite и MySQL — не переключатель без цены

SQLite удобен для локального одиночного приложения и быстрых integration-тестов. MySQL 8.4 LTS предоставляет другой механизм конкурентности, типы и планы. SQL-диалект, блокировки и ограничения проверяются на реальной production-СУБД до релиза.

Не обещайте полную переносимость только потому, что PDO использует единый интерфейс. Абстракция соединения не делает одинаковыми DDL, JSON, datetime, collations и поведение транзакций.

Параметры только для значений

prepare и execute отделяют SQL-шаблон от данных. Имена колонок и направление сортировки выбираются по allowlist готовых фрагментов; placeholder не превращается в идентификатор.

ATTR_ERRMODE устанавливается в EXCEPTION, эмуляция prepared statements выбирается осознанно для драйвера, fetch mode фиксируется. DSN и пароль приходят из защищённой конфигурации и не попадают в response или обычный context лога.

Конкурентное изменение

Два запроса читают одну версию тренировки. UPDATE ... WHERE id = ? AND version = ? увеличивает version; ноль изменённых строк означает конфликт, а не успех. Клиент получает 409 и решает, перечитать ли данные.

SELECT FOR UPDATE полезен для короткого критического участка, но удерживать блокировку во время внешнего API нельзя. Порядок захвата строк должен быть стабильным, чтобы уменьшать deadlock.

Лабораторная работа

Спроектируйте четыре таблицы дневника и транзакцию публикации с history. Добавьте unique/check/foreign key, параметризованный SQL и optimistic version.

Локальный прогресс

Закрепите материал

Отметка, заметка, чек-лист и ответы остаются в localStorage этого браузера и не отправляются в аналитику.

Перелинковка со справочником

Проверка актуальности

  • dev.mysql.comhttps://dev.mysql.com/doc/refman/8.4/en/Первичный источник для актуализации фактов. Адрес приведён как текст и не является активной ссылкой.
  • sqlite.orghttps://www.sqlite.org/lang.htmlПервичный источник для актуализации фактов. Адрес приведён как текст и не является активной ссылкой.

Текст и схемы созданы для этого самоучителя без воспроизведения страниц, иллюстраций и листингов приложенной книги. Проверено: .

Данные этого сервиса

Настройки cookie и локальных данных

Аналитика

Текущий статус: не выбран. До согласия обе аналитические системы не загружаются.

Локальные данные

Удаление затрагивает только ключи PHP-сервиса в этом браузере и требует подтверждения.

Политики

Политика конфиденциальности · Политика использования файлов cookie