38 lines
3.0 KiB
Markdown
38 lines
3.0 KiB
Markdown
---
|
||
aliases:
|
||
- повторяющееся чтение
|
||
tags:
|
||
- зрелость/🌱
|
||
date:
|
||
- - 2024-06-19
|
||
zero-link:
|
||
- "[[00 Базы Данных]]"
|
||
parents:
|
||
- "[[Уровни изоляций транзакций БД]]"
|
||
linked:
|
||
prev: "[[Read committed]]"
|
||
next: "[[Serializable]]"
|
||
---
|
||
**Repeatable read (повторяющееся чтение).** Уровень, при котором читающая транзакция «не видит» изменения данных, которые были ею ранее прочитаны. При этом никакая другая транзакция не может изменять данные, читаемые текущей транзакцией, пока та не окончена. ^38dd4b
|
||
|
||
![](Pasted%20image%2020240619201149.png)
|
||
|
||
Первая транзакция началась. Считала баланс первого пользователя. Обновила его, но не зафиксировала изменения. Началась вторая транзакция. Она также считала баланс первого пользователя, обновила его, но тоже не зафиксировала свои изменения.
|
||
|
||
А теперь правильной окажется та транзакция, которая зафиксирует свои изменения первой. Первая транзакция выполнила коммит первой, поэтому коммит второй транзакции завершился ошибкой.
|
||
|
||
Но если вторая транзакция не изменяла данные, а добавляла новые строчки, то исключения не было бы. Также проблем не будет, если мы обновим баланс второго пользователя.
|
||
|
||
Но возникает закономерный вопрос: что делать с ошибкой, ведь мы хотели выполнить транзакцию, которая свалилась с исключением. Самое простое, что можно сделать — это повторить выполнение второй транзакции с новыми данными. Если исключение возникнет опять, то повторить снова.
|
||
|
||
**Реализация:**
|
||
- [Блокировки](Блокировки.md). Чтение не блокирует запись, а запись не блокирует чтение.
|
||
- [MVCC](MVCC.md)
|
||
|
||
**Особенности:**
|
||
- В [PostgreSQL](00%20PostgreSQL.md) на уровне `REPEATABLE_READ` также предотвращены фантомные чтения.
|
||
|
||
**Проблемы:**
|
||
- [Фантомное чтение](Фантомное%20чтение.md)
|
||
|
||
**Когда использовать:** Вставка новых записей в параллельных транзакциях не влияет на текущую транзакцию. |