Давайте рассмотрим, какие интересные моменты
могут случаться в "черном ящике" Баз Данных:
1) lost update - может случиться, когда две
транзакции одновременно выполняют операцию update над некоторой записью и вторая
транзакция (самая последняя транзакция по времени) заканчивается не удачно, она откатывает все
изменения внесенные первой и второй
транзакцией. Такая ситуация может случиться когда БД не использует блокировок (locking) и конкурирующие транзакции (concurrent
transactions) в ней не изолированы друг
от друга.
2) dirty read - может случиться, когда первая
транзакция изменяет строку, вторая транзакция читает эту строку, первая
откатывает изменения, сделанные в транзакции. Соответственно вторая транзакция имеет не
достоверные данные.
3) unrepeatable read - может случиться, когда первая транзакция дважды читает одну и
ту же строку, и получает разные результаты, в промежутке между двумя чтениями, вторая транзакция изменяет ту же строку, и первая
транзакция при повторном чтении получает
новые данные. Так же частным случаем unrepeatable read является проблема second lost updates
problem. Представьте себе, что две конкурирующих транзакций одновременно читают одну и ту же
строчку, потом первая транзакция изменяет её и завершается удачно (commit),
потом вторая транзакция изменяет ту же строчку и перезаписывает данные, при
этом теряются все изменения внесенные первой транзакцией.
4) phantom read - может случиться, когда одна
и та же первая, транзакция читает строки дважды через какой-то промежуток
времени, и вторая транзакция вставляет новую строчку или удаляет, до второго чтения.
Для предотвращения этих казусов, в ANSI SQL стандарте предусмотрены standard
isolation levels:
1) read
uncommitted transaction isolation - здесь может случиться dirty read, но никогда не случиться lost update. Ни какая транзакция не
может перезаписать не подтвержденные данные, достигается за счет блокировки
(exclusive write locks), однако они могут быть прочтены любой транзакцией.
2) read committed
transaction isolation - здесь может случиться unrepeatable read, но никогда не случиться dirty read. Транзакции
чтения ни когда не блокируют читаемые строки, но при изменении данных,
блокируются изменяемые строки.
3) repeatable
read transaction isolation - здесь может случиться phantom read, но никогда не случиться dirty read и unrepeatable read.
Транзакции чтения блокируют данные строки. И в них не могут писать, ни какие свои
данные транзакции, читать могут все. Транзакции записи блокируют все другие
транзакции.
4) serializable transaction isolation - представьте
очередь из транзакций, и они выполняются одна, за другой по "очереди",
самый высший уровень блокировки.
И так отсюда следует что, чем выше уровень транзакции,
тем неповоротней становиться работа с базой данных, по этому, нужно правильно
выбрать устраивающий вас уровень
транзакции, чем и займемся далее. Каждая база данных имеет по умолчанию transaction
isolation level - обычно это read committed, это чаще
встречается или может быть repeatable
read. Мы конечно можем изменить этот уровень в
объекте java.sql.Connection драйвера JDBC:
1—Read uncommitted isolation
2—Read committed isolation
4—Repeatable read isolation
8—Serializable isolation
или в Hibernate в параметре hibernate.connection.isolation проставить, нужный нам
уровень изоляции транзакции:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database
connection settings -->
<property
name="connection.username">sa</property>
<property
name="connection.password"></property>
...
<property
name="connection.isolation">1</property>
<!--
1—Read
uncommitted isolation
2—Read committed
isolation
4—Repeatable read
isolation
8—Serializable
isolation -->
...
</session-factory>
</hibernate-configuration>
при запуске приложения в логе hibernate появятся такая строчка:
2014-09-10 21:31:32,346 INFO
[org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl]
- <HHH000149: JDBC isolation level: READ_UNCOMMITTED>
Комментариев нет:
Отправить комментарий