0:00
[МУЗЫКА]
[МУЗЫКА] Мы
познакомились с вами понятием транзакции, рассмотрели примеры их использования.
Сейчас рассмотрим,
какие проблемы могут возникнуть при конкурентном доступе к данным.
Первая проблема — это потерянное обновление.
Если один пользователь записывает данные поверх другого,
тем самым стирая изменения, внесенные первым пользователем.
Вторая проблема называется «грязное чтение».
Если мы в процессе нашей работы прочитали данные, записанные другой транзакцией,
а потом выяснилось, что эта транзакция не завершилась успехом.
То есть те данные, которые мы прочитали,
не должны быть зафиксированы в базе данных.
Следующая проблема называется неповторяющееся чтение.
Если мы в процессе работы несколько раз обращаемся к одним и тем же данным и
получаем разные результаты.
Последняя проблема — это фантомное чтение.
Когда у нас в процессе работы в считанном
нами единожды диапазоне впоследствии могут появиться новые записи.
Приведем примеры.
Два пользователя одновременно работают с одним и тем же элементом данных.
Один меняет его и записывает, и второй также записывает.
Изменения, внесенные первым пользователем пропадают.
Такие изменения называются потерянным обновлением.
Следующий пример, «грязное» чтение.
Первый пользователь считал данные, изменил их.
Сразу после этого измененные данные были считаны другим пользователем.
А после этого первый пользователь сказал, что транзакция не фиксируется,
а все ее действия отменяются.
В таком случае второй пользователь прочитал несуществующие данные.
Следующий пример — неповторяющееся чтение.
Оба пользователя считали определенный диапазон значений из одной и той
же таблицы, после этого один пользователь изменил значение, второй
пользователь считывает тот же диапазон и видит, что там значения уже другие.
И на последнем примере вы видите пример фантомного чтения.
Когда второй пользователь два раза считывает один и тот же диапазон,
и во второй раз в диапазоне оказываются новые данные,
добавленные между операциями чтения первым пользователем.
Для того чтобы обезопасить свою работу от таких проблем, кроме начала и
окончания транзакции мы можем еще установить уровень изоляции транзакции.
Выбирая уровень изоляции,
мы хотим обезопасить себя от возникновения некоторых проблем.
Эти уровни изоляции бывают Read uncommitted, что
переводится как незафиксированное чтение, Read committed — фиксированное чтение,
Repeatable read — повторяющееся чтение и Serializable — сложное слово, которое на
русский переводится как сериализуемость и эквивалентность серийному.
Первый уровень изоляции самый низкий, Read uncommitted.
Транзакция устанавливает уровень изоляции Read uncommited,
когда она не хочет останавливаться, ожидая окончание работы другой транзакции,
чтобы понять, зафиксируется вторая транзакция или нет.
Она готова считывать промежуточные данные,
возможно, это не сильно повлияет на ее работу.
Но мы должны при этом понимать, что значения элементов, которые мы прочитаем,
могут не зафиксироваться в базе данных.
Следующий уровень изоляции называется Read committed,
чтение фиксированных транзакций.
В таком случае, если нам потребуется считать диапазон каких-то значений,
а в этот момент данные были изменены другой транзакцией,
которая еще не дошла до конца, в таком случае наши действия блокируются,
мы останавливаемся и ожидаем окончание работы второй транзакции.
И считываем данные после того, как транзакция, изменившая их,
либо зафиксирует их и внесет изменения в данные, либо отменит свои изменения
операцией rollback, и тогда мы считаем прошлые значения данных.
Третий уровень изоляции называется Repeatable read.
Когда мы блокируем считанный нами диапазон,
не позволяя изменять считанный нами диапазон другим транзакциям для того,
чтобы при повторном чтении данные остались неизменными.
Но этот режим позволяет другим транзакциям
вставлять строки в диапазон данных, которые мы прочитали.
Таким образом, мы не исключаем фантомного чтения.
Режим Repeatable read в MySQL является режимом по умолчанию.
Последний уровень изолированности называется Serializable,
или сериализуемость.
Он запрещает другим транзакциям не только вносить изменения в те данные, которые
мы изменяем, и не только мешает изменять данные, которые нами прочитаны, но и
даже не дает другим транзакциям добавлять данные в прочитанный нами диапазон.
Этот режим работы транзакций гарантирует нам избавление от всех возможных
проблем при конкурентном доступе к данным.
Надо заметить, что этот режим дает нам самый низкий уровень параллельного доступа
к данным, поэтому его нужно использовать только при крайней необходимости.
На этой таблице вы видите виды изолированности транзакций,
которые мы рассмотрели, и возможные проблемы,
от которых избавляют или не избавляют наши режимы работы транзакций.
Самый последний режим, сериализуемый, избавляет от всех проблем,
но обеспечивает самый низкий уровень параллельности,
и поэтому на замену ему в некоторых СУБД есть
еще один режим изолированности транзакций, который называется мгновенные снимки.
Как работает этот режим?
На момент начала транзакции для пользователя фиксируется состояние
базы данных, с которым пользователь работает в процессе свой транзакции.
Пользователь может читать данные, изменять их.
И он видит вносимые им самим изменения, но не видит изменений данных,
которые могут происходить при обращении к данным других пользователей.
Когда пользователь в режиме snapshot, мгновенных снимков,
попробует внести изменения в данные, то происходит проверка, не менялись ли
эти данные, которые пользователь хочет изменить, в процессе работы транзакций.
Если данные изменялись, то действия пользователя обрываются,
ему выдается сообщение, что его мгновенный снимок устарел.
Если данные не изменялись в процессе работы транзакций,
то изменения вносятся в базу.
Этот режим не блокирует работу других пользователей, поэтому позволяет большую
степень параллельной обработки данных.