Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Transaction Isolation Levels в БД
Что это
Уровень изоляции определяет как одна транзакция видит изменения другой транзакции. Баланс между консистентностью и производительностью.
4 Уровня изоляции (ISO SQL)
1. READ UNCOMMITTED (Грязное чтение)
// Транзакция A
BEGIN TRANSACTION;
UPDATE accounts SET balance = 1000 WHERE id = 1;
// Не коммитили ещё!
// Транзакция B
BEGIN TRANSACTION;
SELECT balance FROM accounts WHERE id = 1; // 1000 (грязное чтение!)
COMMIT;
// Транзакция A
ROLLBACK; // Отменяем изменения
// Транзакция B видела несуществующие данные
✅ Самый быстрый ❌ Грязное чтение (видишь данные которые могут откатиться)
2. READ COMMITTED (Грязное чтение запрещено)
// По умолчанию в PostgreSQL
// Транзакция A
BEGIN TRANSACTION;
UPDATE accounts SET balance = 1000 WHERE id = 1;
COMMIT;
// Транзакция B
BEGIN TRANSACTION;
SELECT balance FROM accounts WHERE id = 1;
// Пока A не коммитила, B видит старое значение
COMMIT;
✅ Нет грязного чтения ❌ Нечитаемые данные (фантомные строки)
3. REPEATABLE READ (Разные результаты)
// По умолчанию в MySQL InnoDB
// Транзакция A
BEGIN TRANSACTION;
SELECT * FROM accounts; // 1000
// В этот момент другая транзакция вставляет новую строку
SELECT * FROM accounts; // Всё ещё одна строка!
COMMIT;
✅ Повторяемое чтение ❌ Фантомные строки (новые вставки видны)
4. SERIALIZABLE (Полная изоляция)
// Самый строгий уровень
// Транзакции выполняются как одна за другой
// Транзакция A
BEGIN TRANSACTION;
SELECT * FROM accounts WHERE balance > 500;
INSERT INTO accounts VALUES (...);
COMMIT;
// Транзакция B
BEGIN TRANSACTION;
SELECT * FROM accounts WHERE balance > 500;
// Будет ждать пока A завершится
COMMIT;
✅ Полная консистентность ❌ Медленно (много блокировок)
Проблемы изоляции
1. Dirty Read (грязное чтение)
Видишь данные которые не закоммичены
2. Non-Repeatable Read (нечитаемые данные)
Одна строка может измениться в её же транзакции
3. Phantom Read (фантомное чтение)
Новые строки появляются в тех же условиях
4. Serialization Anomaly
Нарушение консистентности из-за параллельности
Матрица проблем
Dirty Non-Rep Phantom Anomaly
READ UNCOMM ✅ ✅ ✅ ✅
READ COMMIT ❌ ✅ ✅ ✅
REP READ ❌ ❌ ✅ ✅
SERIALIZABLE ❌ ❌ ❌ ❌
PostgreSQL пример
-- Проверить текущий уровень
SHOW transaction_isolation;
-- Результат: read committed
-- Изменить уровень
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT * FROM users;
COMMIT;
-- Для одного запроса
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Node.js пример
const client = await pool.connect();
try {
// Установить уровень изоляции
await client.query('BEGIN ISOLATION LEVEL REPEATABLE READ');
// Операции
const user = await client.query('SELECT * FROM users WHERE id = $1', [1]);
await client.query('UPDATE users SET balance = $1 WHERE id = $2', [500, 1]);
// Commit
await client.query('COMMIT');
} catch (e) {
await client.query('ROLLBACK');
throw e;
} finally {
client.release();
}
Реальный пример: Перевод денег
// Проблема: транзакции могут конфликтовать
const transfer = async (fromId, toId, amount) => {
const client = await pool.connect();
try {
// Используем SERIALIZABLE для консистентности
await client.query('BEGIN ISOLATION LEVEL SERIALIZABLE');
// Проверяем баланс
const from = await client.query(
'SELECT balance FROM accounts WHERE id = $1 FOR UPDATE',
[fromId]
);
if (from.rows[0].balance < amount) {
throw new Error('Insufficient funds');
}
// Переводим деньги
await client.query(
'UPDATE accounts SET balance = balance - $1 WHERE id = $2',
[amount, fromId]
);
await client.query(
'UPDATE accounts SET balance = balance + $1 WHERE id = $2',
[amount, toId]
);
await client.query('COMMIT');
} catch (e) {
await client.query('ROLLBACK');
throw e;
} finally {
client.release();
}
};
Выбор уровня изоляции
READ UNCOMMITTED:
✅ Кэш, логирование (не критично)
❌ Финансовые операции
READ COMMITTED:
✅ Большинство приложений
✅ PostgreSQL по умолчанию
❌ Требования максимальной консистентности
REPEATABLE READ:
✅ Отчёты (нужны стабильные данные)
✅ Аналитика
❌ Чувствительно к новым строкам
SERIALIZABLE:
✅ Финансовые операции
✅ Критичные данные
❌ Медленно (конфликты)
Лучшие практики
1. Используй READ COMMITTED по умолчанию
2. Для финансов используй SERIALIZABLE или pessimistic locking
3. Используй FOR UPDATE для критичных строк
4. Минимизируй длину транзакций
5. Monitore deadlock'и и конфликты
Заключение
Уровни изоляции определяют консистентность при параллельных операциях. Баланс между консистентностью и производительностью. Финансовые операции требуют SERIALIZABLE, остальное может быть READ COMMITTED.