0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Не все операции с базой данных можно выразить одним запросом. Например, так нельзя сделать с транзакцией, когда нужно перевести деньги с одного счета на другой. В этом уроке разберем, как выполнять запросы внутри транзакции. Также узнаем, какие существуют требования к транзакционной системе, чтобы она оставалась надежной.</p>
1
<p>Не все операции с базой данных можно выразить одним запросом. Например, так нельзя сделать с транзакцией, когда нужно перевести деньги с одного счета на другой. В этом уроке разберем, как выполнять запросы внутри транзакции. Также узнаем, какие существуют требования к транзакционной системе, чтобы она оставалась надежной.</p>
2
<h2>Запросы внутри транзакции</h2>
2
<h2>Запросы внутри транзакции</h2>
3
<p>Допустим, у нас есть таблица счетов<em>accounts</em>, в которой две записи:</p>
3
<p>Допустим, у нас есть таблица счетов<em>accounts</em>, в которой две записи:</p>
4
<p><a>View on DB Fiddle</a></p>
4
<p><a>View on DB Fiddle</a></p>
5
<p>Процесс перевода можно представить так:</p>
5
<p>Процесс перевода можно представить так:</p>
6
<ol><li><p>Получаем количество денег пользователя:</p>
6
<ol><li><p>Получаем количество денег пользователя:</p>
7
</li>
7
</li>
8
<li><p>Списываем необходимую сумму со счета этого пользователя:</p>
8
<li><p>Списываем необходимую сумму со счета этого пользователя:</p>
9
</li>
9
</li>
10
<li><p>Зачисляем деньги другому пользователю:</p>
10
<li><p>Зачисляем деньги другому пользователю:</p>
11
</li>
11
</li>
12
</ol><p>В результате таблица примет следующий вид:</p>
12
</ol><p>В результате таблица примет следующий вид:</p>
13
<p><a>View on DB Fiddle</a></p>
13
<p><a>View on DB Fiddle</a></p>
14
<p>Одна из проблем в этом процессе -- отсутствует гарантия завершения. Представим, что система успела выполнить списание, и в этот момент произошла ошибка, например, выключили питание или компьютер перезагрузился. В результате получится странная ситуация: деньги списались, но никуда не зачислились:</p>
14
<p>Одна из проблем в этом процессе -- отсутствует гарантия завершения. Представим, что система успела выполнить списание, и в этот момент произошла ошибка, например, выключили питание или компьютер перезагрузился. В результате получится странная ситуация: деньги списались, но никуда не зачислились:</p>
15
<p>Такое может произойти не только с деньгами, но и в большинстве других ситуаций. Приложения по возможности должны находиться в согласованном состоянии. В распределенных системах это невозможно, добиться этого можно с помощью механизма<strong>транзакций</strong>. Мы не будем подробно разбирать эту тему, но вы можете узнать о ней больше, изучив<a>CAP-теорему</a>и<a>Eventual Consistency</a>.</p>
15
<p>Такое может произойти не только с деньгами, но и в большинстве других ситуаций. Приложения по возможности должны находиться в согласованном состоянии. В распределенных системах это невозможно, добиться этого можно с помощью механизма<strong>транзакций</strong>. Мы не будем подробно разбирать эту тему, но вы можете узнать о ней больше, изучив<a>CAP-теорему</a>и<a>Eventual Consistency</a>.</p>
16
<p>Транзакции используют не только в базах данных, но и в обычной жизни. Например, операция снятия денег в банкомате -- это бизнес-транзакция. Пользователи банкомата ожидают, что эта операция либо снимет деньги, либо нет, и банкомат это обеспечивает.</p>
16
<p>Транзакции используют не только в базах данных, но и в обычной жизни. Например, операция снятия денег в банкомате -- это бизнес-транзакция. Пользователи банкомата ожидают, что эта операция либо снимет деньги, либо нет, и банкомат это обеспечивает.</p>
17
<p>Операция снятия денег -- это процесс, который приводит не только к множеству запросов в базу данных, но и к затрагиванию многих систем. У них есть свои процессы и базы данных внутри.</p>
17
<p>Операция снятия денег -- это процесс, который приводит не только к множеству запросов в базу данных, но и к затрагиванию многих систем. У них есть свои процессы и базы данных внутри.</p>
18
<p>Мы ожидаем от любой подобной транзакции<strong>атомарность</strong>-- когда операция либо завершается успешно, либо не проходит. Транзакции в базе данных в этом смысле проще, чем бизнес-транзакции. За обеспечением необходимых гарантий следит сама СУБД, а не программист:</p>
18
<p>Мы ожидаем от любой подобной транзакции<strong>атомарность</strong>-- когда операция либо завершается успешно, либо не проходит. Транзакции в базе данных в этом смысле проще, чем бизнес-транзакции. За обеспечением необходимых гарантий следит сама СУБД, а не программист:</p>
19
<p><a>View on DB Fiddle</a></p>
19
<p><a>View on DB Fiddle</a></p>
20
<p>Транзакции в PostgreSQL -- это блок запросов, который обрамляется запросами:</p>
20
<p>Транзакции в PostgreSQL -- это блок запросов, который обрамляется запросами:</p>
21
<ul><li>BEGIN -- открытие транзакции</li>
21
<ul><li>BEGIN -- открытие транзакции</li>
22
<li>COMMIT -- закрытие транзакции</li>
22
<li>COMMIT -- закрытие транзакции</li>
23
</ul><p>Любая ошибка внутри транзакции откатывает все изменения, которые были сделаны после запроса BEGIN:</p>
23
</ul><p>Любая ошибка внутри транзакции откатывает все изменения, которые были сделаны после запроса BEGIN:</p>
24
<p>Если нужно, транзакцию можно откатить самостоятельно. Для этого необходимо выполнить запрос ROLLBACK до COMMIT. Это нужно, когда выполняются запросы из кода приложения.</p>
24
<p>Если нужно, транзакцию можно откатить самостоятельно. Для этого необходимо выполнить запрос ROLLBACK до COMMIT. Это нужно, когда выполняются запросы из кода приложения.</p>
25
<p><a>View on DB Fiddle</a></p>
25
<p><a>View on DB Fiddle</a></p>
26
<p>Также, чтобы транзакция была надежной и предсказуемой, нужно соблюдать определенные требования.</p>
26
<p>Также, чтобы транзакция была надежной и предсказуемой, нужно соблюдать определенные требования.</p>
27
<h2>Требования к транзакционной системе</h2>
27
<h2>Требования к транзакционной системе</h2>
28
<p>В информатике есть набор требований к транзакционной системе, которые гарантируют ее надежность --<strong>ACID</strong>. К ним относятся:</p>
28
<p>В информатике есть набор требований к транзакционной системе, которые гарантируют ее надежность --<strong>ACID</strong>. К ним относятся:</p>
29
<ul><li>Atomicity (Атомарность)</li>
29
<ul><li>Atomicity (Атомарность)</li>
30
<li>Consistency (Согласованность)</li>
30
<li>Consistency (Согласованность)</li>
31
<li>Isolation (Изолированность)</li>
31
<li>Isolation (Изолированность)</li>
32
<li>Durability (Устойчивость)</li>
32
<li>Durability (Устойчивость)</li>
33
</ul><p>Разберем каждое требование подробнее</p>
33
</ul><p>Разберем каждое требование подробнее</p>
34
<h3>Atomicity (Атомарность)</h3>
34
<h3>Atomicity (Атомарность)</h3>
35
<p>Любая транзакция не может быть частично завершена -- она либо выполнена, либо нет.</p>
35
<p>Любая транзакция не может быть частично завершена -- она либо выполнена, либо нет.</p>
36
<h3>Consistency (Согласованность)</h3>
36
<h3>Consistency (Согласованность)</h3>
37
<p>Завершившаяся транзакция должна сохранять согласованность базы данных. Каждая успешная транзакция фиксирует только допустимые результаты, при том, что в процессе работы транзакции данные могут оказываться несогласованными.</p>
37
<p>Завершившаяся транзакция должна сохранять согласованность базы данных. Каждая успешная транзакция фиксирует только допустимые результаты, при том, что в процессе работы транзакции данные могут оказываться несогласованными.</p>
38
<p>В примере выше снятие денег с одного счета приводит к тому, что данные рассинхронизированы. Но когда транзакция завершается, этого нет.</p>
38
<p>В примере выше снятие денег с одного счета приводит к тому, что данные рассинхронизированы. Но когда транзакция завершается, этого нет.</p>
39
<p>Гарантию согласованности данных нельзя полностью обеспечить только средствами базы данных, например, различными ограничениями. Поддержка этого требования включает в себя работу со стороны программистов, которые пишут необходимый для этого код.</p>
39
<p>Гарантию согласованности данных нельзя полностью обеспечить только средствами базы данных, например, различными ограничениями. Поддержка этого требования включает в себя работу со стороны программистов, которые пишут необходимый для этого код.</p>
40
<h3>Isolation (Изолированность)</h3>
40
<h3>Isolation (Изолированность)</h3>
41
<p>Когда транзакция выполняется, параллельные транзакции не должны оказывать влияния на ее результат. Ни одна транзакция не может увидеть изменения, которые сделаны другими незавершенными транзакциями. Изолированность -- дорогое требование, поэтому в реальных БД существуют режимы, которые изолируют транзакцию не полностью -- уровни изолированности Repeatable Read и ниже.</p>
41
<p>Когда транзакция выполняется, параллельные транзакции не должны оказывать влияния на ее результат. Ни одна транзакция не может увидеть изменения, которые сделаны другими незавершенными транзакциями. Изолированность -- дорогое требование, поэтому в реальных БД существуют режимы, которые изолируют транзакцию не полностью -- уровни изолированности Repeatable Read и ниже.</p>
42
<h3>Durability (Устойчивость)</h3>
42
<h3>Durability (Устойчивость)</h3>
43
<p>Изменения, которые сделаны успешно завершенной транзакцией, должны остаться сохраненными после возвращения системы в работу. И это не должно зависеть от проблем на нижних уровнях, к примеру, обесточивание системы или сбои в оборудовании. Если пользователь получил подтверждение от системы, что транзакция выполнена, он будет уверен, что ничего не отменится из-за какого-либо сбоя.</p>
43
<p>Изменения, которые сделаны успешно завершенной транзакцией, должны остаться сохраненными после возвращения системы в работу. И это не должно зависеть от проблем на нижних уровнях, к примеру, обесточивание системы или сбои в оборудовании. Если пользователь получил подтверждение от системы, что транзакция выполнена, он будет уверен, что ничего не отменится из-за какого-либо сбоя.</p>
44
<h2>Выводы</h2>
44
<h2>Выводы</h2>
45
<p>Мы разобрали, как выполнять запросы внутри транзакции. Такие операции нельзя выполнить за один запрос, поэтому нужно проходить несколько шагов. Также мы узнали, что к транзакционной системе существуют требования ACID: атомарность, согласованность, изолированность и устойчивость. Этот набор свойств транзакции гарантирует, что данные в БД будут целостные независимо от любых сбоев.</p>
45
<p>Мы разобрали, как выполнять запросы внутри транзакции. Такие операции нельзя выполнить за один запрос, поэтому нужно проходить несколько шагов. Также мы узнали, что к транзакционной системе существуют требования ACID: атомарность, согласованность, изолированность и устойчивость. Этот набор свойств транзакции гарантирует, что данные в БД будут целостные независимо от любых сбоев.</p>