Skip to content

Instantly share code, notes, and snippets.

@theaspect
Last active December 12, 2021 20:06
Show Gist options
  • Save theaspect/c26d7eb641979a3facb20f6c1e1c4ac7 to your computer and use it in GitHub Desktop.
Save theaspect/c26d7eb641979a3facb20f6c1e1c4ac7 to your computer and use it in GitHub Desktop.
race and deadlock
-- Atomicity транзакция выполняется либо полностью либо откатывается целиком
-- Consistency если база данных находится в консистентном состоянии (все инварианты выполнены),
-- то после транзакции база останется в консистентном состоянии
-- внутри транзакции консистентность может нарушаться
-- Isolation эффекты одних транзакций не должны влиять на другие транзакции
-- Durability эффекты от завершенной транзакции должны быть устойчивыми
-- Transaction последовательность операций либо выполняется либо отклонояется
-- Инварианты:
-- Суммарный баланс не должен меняться
-- Баланс >= 0
drop table if exists account;
create table account(client varchar(100) primary key, balance int);
insert into account values
('vasya', 100),
('petya', 200);
select * from account;
-- do check in application petya's balance >= 100
-- BEGIN;
update account set balance = balance - 100 where client = 'petya';
update account set balance = balance + 100 where client = 'vasya';
-- COMMIT;
-- ROLLBACK;
select * from account;
-- Race Condition (Lost Update)
-- Connect1 Connect2
-- read petya read petya
-- check petya balance check petya balance
-- petya -100
-- write 100
-- petya -200
-- write 0
BEGIN;
select * from account;
UPDATE account set balance = balance + 10 where client = 'petya';
select * from account;
ROLLBACK;
-- Одновременно во втором коннекте НАЧАЛО
BEGIN;
select * from account;
UPDATE account set balance = balance + 20 where client = 'petya';
select * from account;
COMMIT;
-- Одновременно во втором коннекте КОНЕЦ
-- Option 1 прервать
-- Option 2 перезапустить
-- Deadlock
select * from account;
BEGIN;
UPDATE account set balance = balance + 10 where client = 'petya';
select * from account;
UPDATE account set balance = balance - 1 where client = 'vasya';
select * from account;
COMMIT;
-- Одновременно во втором коннекте НАЧАЛО
select * from account;
BEGIN;
UPDATE account set balance = balance - 10 where client = 'vasya';
select * from account;
UPDATE account set balance = balance + 1 where client = 'petya';
COMMIT;
-- Одновременно во втором коннекте КОНЕЦ
-- Lock, Unlock, Read, Write
-- p == petya
-- v == vasya
-- T1 T2
-- lock(p)
-- lock(v)
-- read(p)
-- read(v)
-- write(p)
-- write(v)
-- lock(v) <- Ждём T2
-- lock(p) <- Ждём Т1
-- обнаружена блокировка
-- rollback T2:
-- unlock(v)
-- блокировка v успешна
-- read(p)
-- write(p)
-- commit:
-- unlock(v)
-- unlock(p)
-- Список Блокировок
-- T1: p
-- T2: v
-- Граф ожидания
-- T1 <-> T2 (цикл в графе)
-- Процесс поиска блокировок периодически строит граф и ищет в нём циклы
-- stale/fair
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment