Изоляции транзакций для собеса в IT на практике в консоли (пробуем гайд с sql на примере Postgresql)

  Рет қаралды 1,286

Кодируем

Кодируем

Күн бұрын

Изоляции Транзакций Практика. Isolation Levels Practice.
Всем привет! Попробуем сегодня немного покодить и имплементировать все аномалии, которые были в предыдущем теоретическом видео в консоли. Посмотрим, как они будут работать и когда не получается решить проблему даже с их помощью. Наверное, запомнить все будет довольно сложно, но найти и быстро самому повторить будет довольно легко, чтобы вспомнить. В процессе записи видео ни одна аномалия не пострадала.
Docker&Pg: gist.github.com/idfumg/c0c2f2...
Pgcli: github.com/dbcli/pgcli
SQL: gist.github.com/idfumg/cd4ce2...
Telegram: t.me/dev_pushkin
Leetcode: leetcode.com/idfumg
GitHub: github.com/idfumg
Gists: gist.github.com/idfumg
0:00 Подготовка
4:13 Read Uncommitted
8:27 Read Committed. Dirty Reads
10:03 Read Committed. Phantom Reads
13:57 Repeatable Read. Phantom Reads
20:19 Write-Skew #0. Repeatable Read
25:47 Write-Skew #0. Serializable
29:04 Lost Update. Read Committed.
32:56 Lost Update. Repeatable Read
35:16 Write-Skew #1. Repeatable Read
38:50 Write-Skew #1. Serializable
42:03 Write-Skew #2. Repeatable Read
46:23 Write-Skew #2. Serializable
48:52 Write-Skew #2. Serializable Failed
53:58 Read-Skew. Repeatable Read
1:00:08 Read-Skew. Serializable
#isolation #isolation_levels #transaction #transaction_isolation_levels #programming #database #interview #job #backend #developer #изоляция #уровни_изоляции #транзакции #изоляция_транзакций #базы данных #бд #интервью #работа #собес #собеседование #бэкенд #разработка

Пікірлер: 42
@kawaikaino5277
@kawaikaino5277 24 күн бұрын
Очень понятно, у вас явно талант, объяснять сложные вещи простыми словами
@nerassstraivaisya
@nerassstraivaisya 27 күн бұрын
Мужик, видосы огонь! А будешь рассказывать про партицирование/шардирование баз данных, настройку репликаций, индексирование? Я бы с удовольствием послушал!
@user-by8um8bk1w
@user-by8um8bk1w Ай бұрын
Канал топ) отличные видео, спасибо
@user-uv6pm4hs3o
@user-uv6pm4hs3o 22 күн бұрын
Про вариант про Lost Update при Serializable вообще в первый раз услышал. Ужас просто :)
@dev_pushkin
@dev_pushkin 22 күн бұрын
Привет! Можешь еще посмотреть обсуждения в комментах про это. Там немного разобрали. В пределах одной транзакции от сервиса - это скорее ошибка мышления "транзакция все сама сделает" + логическая ошибка в коде. Обнаружить возможно даже не сразу получится. Более реальная ситуация - например посылать со странички redmine параллельно запросы на update. Транзакцию долго держать не получится и толку от Serializable никакого не будет. Я об этом хочу в следующем видео побрейнштормить.
@user-uv6pm4hs3o
@user-uv6pm4hs3o 22 күн бұрын
@@dev_pushkin итак понимаю Select for update наше все :)
@amonra3211
@amonra3211 22 күн бұрын
Добрый день! Спасибо за труды, очень полезная информация. И, действительно, такого сборника, да еще и с практикой, в Сети не наблюдалось до Вас. А можете, пожалуйста, дать ссылку на этот 13-ти страничный документ с командами - чтобы можно было тоже протренироваться, но не перепечатывать всё от руки?
@dev_pushkin
@dev_pushkin 20 күн бұрын
Привет! Добавил в описание!
@amonra3211
@amonra3211 20 күн бұрын
​@@dev_pushkin, большое спасибо)
@stasian11
@stasian11 27 күн бұрын
Привет, спасибо за контент) Есть вопросик, возможно глупый. Вот на 17:54 у нас транзакция отлонена ошибкой постгреса. А если бы это было запущено из кода? например из джавы с @Transactional, то мы бы тоже получили ошибку, или фреймворк молча сделал бы ретрай транзакции?
@dev_pushkin
@dev_pushkin 27 күн бұрын
Привет, Стас! На каждом языке в библиотеках возвращается ошибка после выполнения запроса, тип которой можно проверить (или строковый тип, или какого-то рода enumeration, или метод) и самому сделать ретрай (или ничего не делать и вернуть пользователю "повторите еще раз").
@user-fr2dw3qd4v
@user-fr2dw3qd4v 4 күн бұрын
Ошибка на 32:27. Там нет lost update. Вы же просто перетираете все поле новым значением. Если бы вы сеттали "balance + 7" во второй транзакции, то тогда получились бы эти 1514.
@dev_pushkin
@dev_pushkin 3 күн бұрын
Нет никакой ошибки. Посмотри внимательней, что делает сам паттерн в теоретическом видео и тогда получится понять суть. Я эмулирую запрос, который прилетает с разных сервисов параллельно в конкурентной среде по сети в любой момент времени. И вот так он прилетел. Иначе сделать в консоли это просто нельзя. Так же почитай комменты здесь с рассуждениями. Старайся воспринимать не буквально, а видеть паттерн, который за этим стоит и межсетевое взаимодействие.
@dev_pushkin
@dev_pushkin 3 күн бұрын
Также, посмотри видео про способы работы с бд и concurrency control. Станет более понятно это взаимодействие.
@user-fr2dw3qd4v
@user-fr2dw3qd4v 3 күн бұрын
@@dev_pushkin пересмотрел блок из предыдущего видео на 15-й минуте. В принципе, пойнт прежний. Тут не важно, что это с эмуляция запроса с двух серверов. Вы даже если с одного сервиса последовательно такой запрос пришлете, то в итоге будет 1507. Во второй транзакции же даже не читается то, что в изменяемом поле может лежать. Туда просто сеттается новое значение.
@dev_pushkin
@dev_pushkin 3 күн бұрын
Посмотри очень внимательно, что там происходит. Нарисуй на бумажке. Мы читаем из одного сервиса значение и из другого то же значение (пишешь не читаем, что не так). Изоляция у обоих Read Committed. Выполняем какую-то бизнес логику приложения - вычисляем, что нужно старую сумму взять, добавить к ней новое значение и записать в бд. Это происходит конкурентно в каждом из двух сервисов. Изоляция нас не спасает и мы успешно пишем эти значения. Это и есть Lost Update. Уровни изоляции выше могут помочь в таком случае, но не всегда (как мы уже обсуждали в комментах тут). Тут ошибок никаких нет. Есть просто недопонимание работы механизма. Ты, по сути, его и описываешь, говоря, что это не он, используя некое свое понимание его работы. Как ее избежать, я говорю в тех видео, которые выше привел. balance + 7 там тоже есть, но и он не всегда может помочь - это зависит от условия задачи. Посмотри внимательно видео последнее и еще раз продумай ПАТТЕРН работы Lost Update и у тебя сложится картинка. Уже десятки раз обсудили все. Паттерн - мы перезаписываем данные безусловно в разных потоках (транзакция, запрос от сервиса и тд), тем или иным способом, по тем или иным причинам (ошибка в логике, вид и форма задачи и тд), затирая предыдущие данные.
@dev_pushkin
@dev_pushkin 3 күн бұрын
Надеюсь, я тебе помог. Если все еще никак - постарайся больше инфы собрать самостоятельно. Понять, как паттерн работает. Посмотреть примеры другие в статьях.
@IlyaDenisov
@IlyaDenisov Ай бұрын
Привет. Спасибо за доп материал к разбору. Но по-моему на 52:12 нет никакой проблемы, упущенной базой, т.к. вторая транзакция вычитывает состояние, уже изменённое первой (то есть Алиса уже снята с дежурства), в отличие от предыдущего случая, и если несмотря на это программа снимает с дежурства и Боба - то это уже попросту баг в коде программы, который из информации, что на дежурстве единственный сотрудник, всё равно принимает решение снять его с дежурства. Или я что-то упустил?
@dev_pushkin
@dev_pushkin Ай бұрын
Илья, привет! Думаю, это отличный вопрос. По сути, именно так есть. Он немного искусственный. Почему я его выбрал - чтобы показать как раз, что есть ситуации, связанные именно с логикой нашей программы, от которых нас Serializable не спасет. Ключевой момент - транзакции начались вместе, потом действия и комит в разных snapshots. В этом случае, мы без перехлеста сделали такую логику, которая не учитывает зависимость одного состояния от другого. Граф по таким связям не дает нам пересечения. И база данных не может этого никак отследить. У нас получается нормальное последовательное выполнение и доступ вообще к разным полям в разных транзакциях. Мы как люди видим проблему, а бд - нет. Хотя встречал, когда говорили, что такая изоляция уберет все аномалии и можно не париться (Serializable == 0 anomalies, просто копируют одну и ту же картинку :] ). Похожим образом работает Lost Update. В каких-то местах его можно поймать, потом поднимаемся чуть выше или у нас лаг и бам, уже пропускает. Даже если в бд работаем и используем короткие транзакции. Идем еще выше и вообще отловить нельзя оптимально этим одним инструментом. А часто мы не можем транзакцию держать долгое время, это убьет базу. А где-то их вообще нет. Как раз про это в задумке обсуждать в следующем видео. Как не думать про такие вещи постоянно, ведь если плясать только вокруг изоляций мы обязательно пропустим что-то. Ведь никто не идеален и не может все варианты перебрать в голове в каждой задаче :)
@IlyaDenisov
@IlyaDenisov Ай бұрын
​@@dev_pushkin Не могу тут согласиться. Основная тематика уровней изоляции в том, как параллельно выполняемые транзакции могут на друга влиять (то есть насколько они изолированы друг от друга). А в приведённом примере нет этого влияния. Представь, что они не начинались бы одновременно, что вторая транзакция и началась и выполнилась через сутки после первой - всё останется так же, раз в коде состояние, записанное в базе никак не влияет на принимаемое решение вообще, то есть в том коде, который приведён для второй транзакции вообще нет логики приятия решения - действие выполняется безусловно, независимо от вычитанных данных. Поэтому нельзя сказать, что тут человеку очевидно, что-то, что не заметила база - там нечего и замечать. Выполнилась ли первая транзакция до второй, или наоборот, или они параллельно выполнялись - никакой разницы в поведении нет, т.к. в коде прямо заложено - снять обоих врачей с дежурства, невзирая ни на что. Так что это всё же не похоже на lost update - в тех примерах логика каждой из транзакций "увеличить значение на столько-то", то есть имеется влияние текущего состояния на конечное. Однако, не могу утверждать, что нет ситуаций, где serializable не побеждает какой-то баг (хотя и почти уверен в этом), но данный кейс его, увы, не демонстриует. Либо я что-то важное упускаю.
@IlyaDenisov
@IlyaDenisov Ай бұрын
На всякий случай явно пропишу наблюдение - "select * from doctors where username = 'bob';" уже говорит, что боб НЕ на дежурстве, но следующая команда всё равно снимает с дежурства Алису. Т.е. копия данных, фиксированная для второй транзакции, это не снапшот на момент начала транзакции, а снапшот на момент выполнения этого select.
@dev_pushkin
@dev_pushkin Ай бұрын
@@IlyaDenisov Я понял, в чем мы разошлись. В целом, я это и имел в виду. Заметь, что этот пример из тех же операций, что и предыдущий, только по времени они выполнились в другом порядке. Если, например, сделать сначала два селекта и потом комит, то pg отловит эту ситуацию и последняя транзакция зафейлится. Например, в предыдущем примера, транзакция вторая зафейлилась. Кажется, что все четко. Но не совсем. Нет гарантий, что код будет выполнен как (2 selects + 2 commits) или (1 select & 1 commit) + (1 select & 1 commit). Они выполняются параллельно и любая из них может подзависнуть из-за, например, системного context switch или scheduling ядром Linux (причем и для нашего сервиса или консоли, и для самой бд актуально, так как там форкается процесс на каждое соединение и процессы будут управляться Linux), или перерывы на посылку запроса. Или же они успеют обе сделать селект. Думать, что если мы успели создать две транзакции и это дает нам изолированное поведение и снапшот (и защищает нас от ошибок) - не всегда верно. Есть определенный набор логических условий и зависящих факторов конкурентности, когда оно не сработает. То есть два потока могут переставить (паузы во времени, не реальная перестановка) эти наши statements в рантайме таким образом, что случится ровно вот такое параллельное выполнение, но в sequential манере, ровно друг за другом. И уже в данном случае, не будет второго селекта, по которому pg увидит связь с первым селектом по той же таблице. Я по факту сделал тот же самый пример, что и до этого, переставив (паузы во времени, не реальная перестановка) statements местами, что может в рантайме легко произойти. Поэтому одна и таже последовательность действий, в одном случае влияет друг на друга, во втором нет. А код на клиенте один и тот же.
@dev_pushkin
@dev_pushkin Ай бұрын
@@IlyaDenisov Про Lost Update я, конечно, не имел в виду, что это его пример. Больше как аналогия или схожесть выполнения некоторых последовательностей действий друг за другом таким образом, что мы теряем влияние друг на друга обоих действий. В том случае - это перезапись значения поверх старого, а здесь - как-бы запись в набор данных (если представить его как множество) один раз и следом другой опять. И в прошлом примере операции легли так, что pg выдал ошибку. А в этом тот же самый код не привел к ошибке из-за пауз во времени в конкурентной среде.
@BurgerChannel
@BurgerChannel 22 күн бұрын
а на гугл док с командами есть линка?
@dev_pushkin
@dev_pushkin 20 күн бұрын
Привет! Добавил в описание!
@BurgerChannel
@BurgerChannel 20 күн бұрын
​@@dev_pushkin❤
Не пей газировку у мамы в машине
00:28
Даша Боровик
Рет қаралды 4 МЛН
Маленькая и средняя фанта
00:56
Multi DO Smile Russian
Рет қаралды 2,4 МЛН
Учим Базы Данных за 1 час! #От Профессионала
1:07:50
Хауди Хо™ - Просто о мире IT!
Рет қаралды 488 М.
Транзакции | Основы SQL
7:16
Andrey Sozykin
Рет қаралды 44 М.
Оператор SELECT | Основы SQL
7:01
Andrey Sozykin
Рет қаралды 117 М.
Что такое ACID за 9 минут
9:46
Listen IT
Рет қаралды 29 М.
Programming Fundamentals - #1 - Logic and algorithms
15:29
loftblog
Рет қаралды 1,5 МЛН
PostgreSQL, MVCC, транзакции, блокировки, уровни изоляции транзакций.
9:12
Быстро и полезно о разработке на 1С
Рет қаралды 3,7 М.
❌УШЛА ЭПОХА!🍏
0:37
Demin's Lounge
Рет қаралды 323 М.
Creepy Samsung Alarm cannot be turned off 😱🤣 #shorts
0:14
Adani Family
Рет қаралды 1,6 МЛН
Any Sound & Call Recording Option Amazing Keypad Mobile 📱
0:48
Tech Official
Рет қаралды 326 М.
How much charging is in your phone right now? 📱➡️ 🔋VS 🪫
0:11