Определение транзакции
Транзакция будет включать большое количество операций ЦП и операций ввода-вывода, которые будут упакованы в единицу выполнения, либо завершены одновременно, либо не завершены одновременно.
Транзакция — это группа атомарных команд SQL или независимая единица работы.Если какой-либо из операторов SQL не выполняется из-за сбоя или по другим причинам, то все операторы SQL в группе не будут выполнены. Если начальная транзакция не отображается, база данных автоматически фиксирует каждую операцию sql в соответствии со значением autocommit.
Характеристики транзакции ACID
Атомарность (А)
Все операции в транзакции либо завершены, либо не выполнены, для транзакции невозможно выполнить только часть из них.
Консистенция (С)
База данных всегда переходит из одного согласованного состояния в другое согласованное состояние.
Изоляция (я)
Изменения, сделанные одной транзакцией, не видны другим транзакциям, пока они не будут окончательно зафиксированы. Операции между несколькими транзакциями не влияют друг на друга. Каждое понижение уровня изоляции транзакции может улучшить параллелизм базы данных, но в то же время увеличить незащищенность. Уровень изоляции транзакций будет подробно рассмотрен позже. Вот краткое введение:
- Чтение незафиксированных: другие транзакции могут читаться без фиксации.
- Чтение подтверждено: другие транзакции могут быть прочитаны только в том случае, если они зафиксированы.
- Повторяемое чтение: Только состояние, когда транзакция запускается сама по себе, не зависит от других транзакций.
- Сериализация: совершение транзакций по порядку обеспечивает безопасность данных, но не может обеспечить параллелизм.
Стойкость (D)
Как только транзакция зафиксирована, она должна быть обновлена в базе данных и не может быть отменена. Даже если сервер не работает, все равно необходимо автоматически выполнить команду sql в транзакции при следующем запуске и отразить это в базе данных.
изоляция транзакций базы данных
представлять
обособленный сектор | грязное чтение | неповторяемое чтение | галлюцинации |
---|---|---|---|
Читать незафиксированные | возможно | возможно | возможно |
Чтение зафиксировано | невозможный | возможно | возможно |
Повторяемое чтение | невозможный | невозможный | возможно |
Сериализуемый | невозможный | невозможный | невозможный |
- Чтение незафиксированных: Разрешено грязное чтение, то есть данные, измененные незафиксированными транзакциями в других сеансах, могут быть прочитаны.
- Чтение подтверждено: только данные, которые были зафиксированы, могут быть прочитаны. Большинство баз данных, таких как Oracle, по умолчанию используют этот уровень.
- Повторяемое чтение: Повторяемое чтение. Запросы в рамках одной и той же транзакции согласованы в начале транзакции, уровне InnoDB по умолчанию. В стандарте SQL изменение уровня устраняет неповторяющиеся чтения, но фантомные чтения все еще существуют, но InnoDB решает фантомные чтения.
- Сериализация: полностью сериализованное чтение, при каждом чтении требуется общая блокировка на уровне таблицы, а операции чтения и записи будут блокировать друг друга.
Подготовить данные
Подготовьте таблицу учетных записей с тремя полями в таблице, а именно идентификатором первичного ключа, именем учетной записи и суммой.
create table account(
id int(11) not null auto_increment,
customer_name varchar(255) not null,
money decimal(10,2) not null,
primary key(id),
unique uni_name using btree (customer_name)
) ENGINE = 'InnoDB' AUTO_INCREMENT=10 COMMENT = '账户表';
Проверить RU (незафиксированное чтение)
1. Откройте два сеанса и установите уровень изоляции для чтения незафиксированных
set session transaction isolation level read uncommitted;
select @@session.tx_isolation;
2. Сессия 1 открывает транзакцию 3. Сеанс 2 запускает транзакцию и вставляет часть данных 4. Сеанс 1 начинает запрашивать базу данных и находит незафиксированные данные транзакции сеанса 2. 5. Если сеанс 2 откатывается в это время, сеанс 1 не может быть найден. Сводка. В режиме RU одна транзакция может считывать данные другой незафиксированной транзакции, что приводит к грязному чтению. Откат другой транзакции приведет к несогласованности данных. RU — самый низкий уровень изоляции транзакций.
RC (фиксация чтения)
1. Установите уровень изоляции сеанса 1 и сеанса 2 в режим чтения-фиксации.
set session transaction isolation level read committed;
2. И сеанс 1, и сеанс 2 запускают транзакции, а сеанс 1 запрашивает текущие данные.
3. Сессия 2 обновляет данные, но не отправляет их, а сессия 1 запрашивает текущие данные и до сих пор не изменилась
4. Но сеанс 2 отправляет транзакцию в это время, а сеанс 1 запрашивает текущие данные для изменения
Резюме: в режиме RC мы обнаружили, что когда другая транзакция не фиксирует изменение данных, текущая транзакция не может прочитать измененные данные, что позволяет избежать грязного чтения в режиме чтения незафиксированного. Но есть проблема, в текущей транзакции данные двух выборок различаются, из-за чего возникает проблема неповторяющегося чтения. PS: уровень изоляции RC — это уровень изоляции по умолчанию для базы данных Oracle.
RR (повторяющееся чтение)
1. Установите уровень изоляции сеанса 1 и сеанса 2 на повторяемое чтение.
set session transaction isolation level repeatable read;
2. Сеанс 1 открывает транзакцию и запрашивает текущие данные, а сеанс 2 открывает транзакцию и обновляет данные.
3. В настоящее время данные запроса сеанса 1 по-прежнему являются предыдущими данными.
4. Затем сеанс 2 отправляет транзакцию, а сеанс 1 запрашивает данные или предыдущие данные, что означает, что изменение сеанса 2 не влияет на текущую транзакцию и может быть прочитано повторно.
5. В это время сеанс 1 отправляет текущую транзакцию, снова считывает данные и обнаруживает, что другие транзакции изменили данные.
Резюме: В режиме RR мы решаем проблему неповторяющегося чтения, то есть при этом уровне изоляции мы можем гарантировать получение одних и тех же данных в транзакции (даже если другие транзакции изменяют текущую строку данных). Однако фантомного чтения не избежать.Простое объяснение фантомного чтения заключается в том, что при добавлении новых данных нет гарантии, что данные, полученные дважды, будут противоречивыми.Однако разные базы данных имеют разные реализации для разных уровней RR и иногда добавляют блокировку пробелов, чтобы избежать фантомных чтений.
InnoDB решает проблему фантомного чтения
В заключение
Во-первых, вывод:Под уровнем изоляции RR, InnoDB использует MVCC и блокировку следующего ключа (блокировку промежутка) для устранения фиктивных операций чтения. MVCC разрешает фантомное чтение обычного чтения (чтение моментального снимка), а блокировка пробела разрешает фантомное чтение в текущей ситуации чтения.
Что такое фантомное чтение
(Первое утверждение: в режиме RR движком является InnoDB, который не может производить следующие эффекты.)
1. Транзакция 1 выполняется первой, но не фиксируется
start transaction;
update account set account=1000 where id>10;
Результат: OK строка xx имя таблицы успешно повлияло на количество строк 2. Выполнить после транзакции 2 и отправить
start transaction;
insert into account(customer_name, money) values('李云龙',10000);
commit;
3. Выберите транзакцию 1 еще раз, и набор результатов будет следующим:
select * from account;
Ли Юньлун, 10000 г.
В это время транзакция 1 перегружена.Разве количество всех с id>10 не обновляется до 1000?Почему есть лишний человек с суммой 10000? Это влияние зафиксированной транзакции 2 на транзакцию 1, которое называется фантомным чтением.
Разница между фантомным чтением и неповторяемым чтением
Неповторяемое чтение: прочитайте запись несколько раз и обнаружите, что некоторые значения столбцов в записи были изменены.
Фантомное чтение: до тех пор, пока это относится к чтению записей в диапазоне несколько раз (включая прямой запрос всех результатов записей или выполнение сводной статистики) и обнаружению противоречивых результатов (обычно относится к увеличению количества записей, следует также учитывать сокращение количества записей). как фантомное чтение).
Как решить иллюзию
текущее чтение
Так называемое текущее чтение относится к заблокированному оператору выбора (блокировка S или X), обновлению или удалению. При уровне изоляции транзакций RR база данных будет использовать гэп-блокировки для блокировки этой записи и диапазона индекса. Например:
выберите * из учетной записи, где id> 10 для обновления; блокирует запись с id = 10 и диапазоном id> 10, чтобы избежать вставки записей между диапазонами, чтобы избежать записей фантомных строк.
нормальное чтение
Поскольку обычное чтение — это чтение без блокировки, решением для фантомного чтения является MVCC. MVCC добавит некоторые вспомогательные поля в каждую строку кортежа для записи номера версии создания и номера версии удаления. В начале каждой транзакции имеется уникальный добавочный номер версии. Каждый раз, когда открывается новая транзакция, номер версии транзакции увеличивается. При уровне изоляции MYSQL по умолчанию (повторяющееся чтение) добавление, удаление, изменение и запрос становятся следующими:
- select: чтение записей, созданная версия которых меньше или равна текущему номеру версии транзакции, а версия удаления равна нулю или больше, чем текущий номер версии транзакции. Это гарантирует, что запись существует до чтения.
- вставка: сохранить номер версии текущей транзакции в созданный номер версии строки.
- update: вставьте новую строку и используйте текущий номер версии транзакции в качестве номера версии создания новой строки и установите номер версии удаления исходной строки записи в качестве номера текущей версии транзакции.
- удалить: сохранить текущий номер версии транзакции в номер версии удаления строки. Это немного сбивает с толку.Подводя итог, есть еще два номера версии в строке, один для номера версии создания и один для номера версии удаления, оба из которых являются номерами версии сохраненной транзакции. Давайте рассмотрим пример, чтобы понять: например, если я вставлю запись с идентификатором транзакции = 1, то запись будет следующей:
id | name | createversion | deleteversion |
---|---|---|---|
1 | Джек Ма | 1 |
Если я обновлю имя на Liu Qiangdong и идентификатор транзакции = 2, запись станет
id | name | createversion | deleteversion |
---|---|---|---|
1 | Джек Ма | 1 | 2 |
2 | Лю Цяндун | 2 |
=> Видно, что версия удаления исходного предка является идентификатором обновленной транзакции, и добавляется новая.
Если вы удалите его, предполагая, что идентификатор транзакции = 3, удалите запись с идентификатором = 2
id | name | createversion | deleteversion |
---|---|---|---|
1 | Джек Ма | 1 | 2 |
2 | Лю Цяндун | 2 | 3 |
Ключевым моментом является то, что если я прочитаю это сейчас, то должны быть соблюдены одновременно два условия:
1. Версия создания чтения меньше или равна номеру версии текущей транзакции, что означает, что данные были созданы до этой транзакции
2. Удалите записи, версия которых пуста или больше текущей версии транзакции. Это означает, что операция удаления происходит после этой транзакции.
Итак, когда транзакция 1 вставляет запись, транзакция 2 обновляет эту запись и удаляет эту запись, транзакция 1 снова запрашивает эту запись, только запись с id=1 удовлетворяет этим двум условиям, поэтому результат: (избегайте фантомного чтения)
id | name | createversion | deleteversion |
---|---|---|---|
1 | Джек Ма | 1 | 2 |
сериализовать
Все транзакции выполняются последовательно, что является наивысшим уровнем изоляции и наихудшей производительностью.
Суммировать
Эта статья здесь, в целом, четыре характеристики ACID транзакций базы данных и четыре уровня изоляции (RU, RC, RR, сериализация) и проблемы, которые возникнут (грязные чтения, неповторяемые чтения, фантомные чтения) ) - это высокая -частотный вопрос в интервью.Все нужно накапливать, а затем многократно пересматривать, чтобы память и понимание могли быть более глубокими.