По-настоящему понять уровень изоляции повторяющихся транзакций чтения

задняя часть база данных MySQL
По-настоящему понять уровень изоляции повторяющихся транзакций чтения

Оригинал: Code Logs (идентификатор общедоступной учетной записи WeChat: codelogs), добро пожаловать в общий доступ, пожалуйста, сохраните источник для перепечатки.

Бизнес-профиль

Стандарт SQL определяет четыре уровня изоляции:

Незафиксированное чтение (READ UNCOMMITTED): на этом уровне изоляции могут происходить грязные чтения, неповторяемые чтения и фантомные чтения.
READ COMMITTED: Решите проблему грязного чтения.
ПОВТОРЯЕМОЕ ЧТЕНИЕ: Решите проблему грязного чтения и неповторяемого чтения.
Сериализация (SERIALIZABLE): Решите проблемы грязных чтений, неповторяемых чтений и фантомных чтений.

Феномен грязного чтения, неповторяемого чтения и фантомного чтения здесь подробно объясняться не будет.Статьи или книги, посвященные транзакциям, в основном объяснят это, но обратите внимание, что все эти явления могут возникать при одновременном выполнении транзакций. , и не может быть понято. Для ошибок базы данных!

Но когда я думаю об этом знании после многих лет работы, у меня возникает очень большой вопрос о повторяемом поведении чтения, а именно:

  1. Почему программисты не хранят данные, прочитанные в первый раз, в памяти и повторно используют их во второй раз? Почему база данных должна гарантировать, что данные, прочитанные дважды, будут одинаковыми (которые могут быть прочитаны повторно), а двукратное чтение базы данных приведет к трате большего количества ресурсов базы данных и снижению производительности.
  2. Кроме того, что плохого в том, чтобы каждый раз читать последние данные? Какая польза от чтения исторических данных?

В таком случае, какой смысл в повторяемом чтении?

Например

Мы можем рассмотреть следующие сценарии.Есть финансовый продукт, который имеет функцию.Необходимо найти тех пользователей, у которых баланс счета и поток транзакций по счету не совпадают.Вызовем задачу переноса счета, и когда выполняется задача сверки счетов , транзакция пользователя проходит нормально без перерыва.
Например, если баланс счета составляет 100 юаней, счет имеет две записи транзакций (+200, -100), поэтому учетная запись сверяется нормально, но если программа запрашивает баланс счета 100 юаней, то пользователь переводит еще 100 юаней. Когда мы снова запросим записи транзакций, мы обнаружим разные результаты для разных уровней изоляции транзакций, а именно:

Отправить для чтения повторяемое чтение Примечание
Начальный баланс 100, история транзакций (+200, -100)
Проверьте баланс 100 юаней Проверьте баланс 100 юаней
Другая транзакция тратит 100 юаней, баланс уменьшается до 0, и отправить
Запрос к записям транзакций (+200, -100, -100) Запрос к записям транзакций (+200, -100)
Согласование не удалось Примирение удалось

Видно, что в сценарии чтения с фиксацией сверка не удалась, но в сценарии с повторяющимся чтением сверка прошла успешно, фактически баланс счета и записи транзакций всегда совпадают. Лично проверял в MySQL5.7, результат действительно так.

Итак, какова конкретная роль повторяемого чтения?
Итак, какова конкретная роль повторяемого чтения?
Итак, какова конкретная роль повторяемого чтения?

Его основная функция состоит в том, чтобы гарантировать, что после открытия транзакции запрос всех табличных данных в базе данных будет запрашивать ту же версию, которая является версией на момент открытия транзакции (в mysql версия на момент открытия транзакции). первый запрос), и независимо от того, запрашивается ли это таблица или другая таблица, уровень транзакции повторяемого чтения не устраняет очевидное явление неповторяемого чтения.

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

Этот пример также иллюстрирует другую проблему, а именно, когда вам нужно использовать транзакцию? Когда мы впервые пишем код, нам часто говорят, что все операции записи должны быть помещены в одну транзакцию. операции также должны быть помещены в одну транзакцию в бизнесе.

Взгляните на бизнес с другой точки зрения

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

  1. Незафиксированное чтение не решает проблемы согласованности чтения, а только обеспечивает согласованность записи (также известную как атомарность) транзакции.После фиксации транзакции либо все модификации будут успешными, либо ни одна из них не будет успешной.
  2. Подтвердите чтение, чтобы убедиться, что модификации других параллельных транзакций либо видимы, либо невидимы, что можно понимать как «согласованное чтение записи», обратите внимание на сегментацию предложений! «Консистентность записи» и «Чтение», которые являются наиболее часто используемыми уровнями изоляции транзакций, могут обеспечить согласованность значения бизнес-данных.

Например, если пользователь размещает заказ, открытая транзакция последовательно записывает данные заказа в основную таблицу заказов и данные заказа в подтаблицу order_item. пишет, прочитайте заказ и заказ_элемент, вы обнаружите, что я только прочитал заказ, но не заказ_элемент. Это будет шоком для пользователя, увидев. Я заплатил деньги и купил пустой заказ! Хотя пользователь обновляется и может видеть полные данные.
Однако, если используется уровень изоляции фиксации чтения транзакции, такой проблемы не будет, пользователь может либо не найти какие-либо данные, либо найти полные данные, что также показывает со стороны, что логически связанную модификацию данных необходимо оперировать открытием транзакция.
3. Повторяющееся чтение, чтобы гарантировать, что в момент открытия транзакции или выполнения первого запроса все последующие чтения всех таблиц во всей БД будут версией на момент чтения, разумеется, включая повторное чтение одной и той же таблицы , что также можно понимать как «согласованное чтение версии».
4. Сериализация, как правило, устраняет логические ошибки параллелизма, потому что этот уровень логики может считать, что все транзакции выполняются последовательно (хотя база данных может фактически выполняться одновременно).
Например, две транзакции сначала определяют, есть ли данные, а затем вставляют данные, если данных нет. В случае параллелизма две транзакции запрашивают одновременно, а затем вставляют данные, обнаружив, что данных нет. результат, два куска данных вставляются, но уровень изоляции сериализации не имеет этого.Проблема, это называется состоянием гонки в параллельном программировании, поэтому сериализация решает проблему условий гонки чтения и записи.
Конечно, эту проблему также можно решить, добавив уникальный индекс или используя метод внешней блокировки дисплея.

Решает ли повторяющееся чтение MySQL фантомное чтение?

В Интернете мы часто видим два вида статей, одни говорят, что повторяющееся чтение mysql решает проблему фантомного чтения, а другие говорят, что не решают проблему.
Это правда или нет Конкретная разница заключается в том, является ли текущая операция чтения чтением моментального снимка или текущим чтением, как показано ниже:

Снимок прочитан текущее чтение Примечание
В начале есть два order_item под заказом 1, A и B соответственно
выберите * из order_item, где oid=1 (читается A и B) выберите * из order_item, где oid=1 (читается A и B) первый раз читаю
Другая транзакция вставляет C в порядке 1 и фиксирует
выберите * из order_item, где oid=1 (читается A и B) выберите * из order_item, где oid=1 для обновления (читается A, B и C) второе чтение

Приведенные выше результаты также проверены в mysql5.7, и мы вызываемselect xxx for updateДля текущего чтения, то есть для чтения последних данных, обычный выбор - чтение моментального снимка в mysqlinsert、update、delete、select xxx for updateВсе сейчас читают.

Кроме того, еслиselect xxx for updateзаменитьupdate order_item set price=199 where oid=1Также возможно обновить до 3-х частей данных, потому что обновление является текущим чтением.Интересно, что вы также можете найти 3 части данных, используя обычный выбор позже.Я подозреваю, что обновление изменило версию данных на версия текущей транзакции, полученная в виде снимка Вы также можете найти ее, прочитав Если у вас есть глубокое понимание принципа mysql mvcc, вы также можете сказать, верно ли ваше понимание.

Следовательно, mysql решает проблему фантомного чтения при чтении моментальных снимков и не решает проблему фантомного чтения при текущем чтении, но независимо от того, решает ли он проблему фантомного чтения или нет, он не может заменить уровень изоляции сериализации.

Прошлый контент

Навыки работы с текстовыми командами в Linux (часть 2)
Навыки работы с текстовыми командами в Linux (часть 1)
Оказывается awk действительно артефакт
Полезная параллельная команда
Сводка общих сетевых команд