MySQL и PostgreSQL

Транзакции и блокировки в MySQL и PostgreSQL: кто лучше защищает данные

И MySQL, и PostgreSQL поддерживают транзакции и умеют защищать данные от искажений при параллельной работе, но делают это немного по-разному: PostgreSQL изначально строился вокруг многоверсионности данных, а MySQL получил полноценную транзакционность позже вместе с движком InnoDB. На практике это влияет на то, как быстро база справляется с одновременными запросами на чтение и запись.

Что вообще такое транзакция и зачем она нужна?

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

Обе СУБД поддерживают ACID-транзакции: PostgreSQL — всегда, а MySQL — только если данные хранятся в движке InnoDB, который сейчас установлен по умолчанию. Старый движок MyISAM транзакции не поддерживает вовсе, поэтому если вы видите базу на MyISAM — это повод насторожиться и проверить, не потеряются ли данные при сбое.

Что такое блокировки и почему без них нельзя?

Когда два пользователя одновременно пытаются изменить одну и ту же строку в таблице, база должна как-то развести их во времени, иначе изменения перепишут друг друга или получится каша из полуприменённых правок. Для этого используются блокировки — механизм, который временно ограничивает доступ к данным для других транзакций, пока текущая не завершится.

Блокировки бывают разного уровня: можно заблокировать всю таблицу, а можно — только конкретную строку. Чем мельче блокировка, тем больше пользователей могут работать параллельно без ожидания. И MySQL, и PostgreSQL умеют блокировать на уровне строк, что значительно эффективнее блокировки целых таблиц.

Чем отличается подход PostgreSQL к параллельной работе?

PostgreSQL использует технологию MVCC — многоверсионный контроль параллелизма. Суть в том, что при изменении строки база не переписывает её сразу, а создаёт новую версию, оставляя старую видимой для тех транзакций, которые её уже читают. Благодаря этому чтение практически никогда не блокирует запись, и наоборот: пока один пользователь читает данные, другой может их спокойно менять.

Обратная сторона MVCC — накопление «мёртвых» версий строк, которые со временем нужно убирать. Для этого в PostgreSQL есть встроенный процесс автоочистки, который работает в фоне и подчищает устаревшие версии данных, освобождая место.

А как с этим справляется MySQL?

MySQL с движком InnoDB тоже использует многоверсионность, во многом похожую на подход PostgreSQL, но реализованную иначе — старые версии строк хранятся в отдельной служебной области, а не прямо в таблице. Это тоже позволяет читателям не мешать писателям в большинстве сценариев.

Важное отличие — уровни изоляции транзакций по умолчанию. У MySQL это Repeatable Read, у PostgreSQL — Read Committed. Разница влияет на то, увидит ли транзакция изменения, сделанные другими транзакциями уже после её начала. Оба уровня входят в стандарт SQL, и оба варианта — рабочие, просто дают разное поведение в пограничных ситуациях, например при повторном чтении одной и той же строки внутри длинной транзакции.

Клауд АйСи — цифровые сервисы для бизнеса в одном кабинете: 1С в облаке с ежедневными резервными копиями, конструктор сайтов, Умный онлайн-чат и проверка контрагентов.
Ваши данные под защитой. Есть бесплатные тарифы навсегда.

Что такое дедлоки и у кого они случаются чаще?

Дедлок, или взаимная блокировка, — это ситуация, когда две транзакции заблокировали разные ресурсы и ждут друг друга, а разблокировать никто не может, потому что каждая ждёт своей очереди. Классический пример: транзакция А заблокировала строку 1 и хочет заблокировать строку 2, а транзакция Б в это время сделала наоборот. Получается тупик.

Обе СУБД умеют обнаруживать такие ситуации автоматически и принудительно прерывают одну из транзакций, чтобы разорвать цикл ожидания. Приложению просто нужно быть готовым к тому, что транзакция иногда завершится с ошибкой из-за дедлока, и в этом случае стоит повторить попытку. Частота дедлоков больше зависит от структуры запросов и логики приложения, чем от самой СУБД — при плохо спроектированных транзакциях они будут случаться в любой базе.

Какая СУБД лучше держит нагрузку с большим числом одновременных запросов?

Однозначного победителя тут нет, слишком многое зависит от характера нагрузки. PostgreSQL традиционно хвалят за более предсказуемое поведение при сложных транзакциях со множеством связанных таблиц и за качественную реализацию сериализуемого уровня изоляции — самого строгого, который гарантирует, что результат параллельного выполнения транзакций будет таким же, как если бы они шли строго по очереди.

MySQL исторически силён в сценариях с большим количеством простых, коротких транзакций — типичных для веб-приложений, где пользователи в основном читают данные и изредка что-то обновляют. Многое также зависит от настроек конкретного сервера, версии СУБД и того, насколько грамотно спроектирована схема данных и индексы.

Что важно учитывать разработчику на практике?

Вот несколько практических моментов, которые стоит держать в голове при работе с транзакциями в обеих СУБД:

  • Держите транзакции короткими — чем дольше транзакция открыта, тем выше шанс конфликта с другими и тем больше «мусора» накапливается в базе.
  • Всегда обрабатывайте в коде приложения возможность отката транзакции из-за дедлока или конфликта сериализации.
  • Проверяйте, какой движок хранения используется в MySQL — таблицы должны быть на InnoDB, а не на устаревшем MyISAM.
  • Изучите уровни изоляции обеих СУБД перед стартом проекта — значение по умолчанию не всегда подходит именно вашей задаче.
  • Следите за автоочисткой в PostgreSQL на высоконагруженных базах — если она не успевает работать, производительность может постепенно деградировать.

Как выбрать между MySQL и PostgreSQL с точки зрения транзакций?

Если проекту важна строгая согласованность данных при сложной бизнес-логике — например, в финансовых или учётных системах с множеством связанных таблиц — PostgreSQL обычно чувствует себя увереннее благодаря более гибкой настройке уровней изоляции и надёжной реализации MVCC. Если же нагрузка состоит из большого количества простых операций, как в типичных веб-сервисах и интернет-магазинах, MySQL справится не хуже и часто требует меньше тонкой настройки.

Развёртывание и последующее администрование любой из этих СУБД — задача, отнимающая время у команды разработки. В «Клауд АйСи» можно получить готовую к работе базу данных на MySQL или PostgreSQL в облаке с уже настроенным резервным копированием и мониторингом, чтобы сосредоточиться на логике приложения, а не на конфигурации сервера баз данных.

1С в облаке с резервным копированием

Зарегистрируйтесь и подключите облачную 1С — ежедневные бэкапы и обновления уже включены.

Частые вопросы

Что произойдёт, если транзакция прервётся из-за дедлока?

СУБД автоматически откатит одну из конфликтующих транзакций и вернёт приложению ошибку. Все изменения этой транзакции отменятся, и приложению нужно повторить операцию заново.

Можно ли в MySQL использовать транзакции без InnoDB?

Нет, старый движок MyISAM транзакции не поддерживает. Для работы с транзакциями таблицы должны использовать движок InnoDB, который в современных версиях MySQL установлен по умолчанию.

Что такое сериализуемый уровень изоляции и когда он нужен?

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

Влияет ли MVCC на объём базы данных?

Да, при активной записи в PostgreSQL накапливаются старые версии строк, которые убираются процессом автоочистки. Если процесс не успевает за нагрузкой, размер базы и время выполнения запросов могут расти.