Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Фантомное чтение на Read Committed - есть или нет?  [new]
Alex Akopov
Member

Откуда: Киев
Сообщений: 5
Доброй ночи.

Пытаясь исследовать уровни изоляции и блокировки, столкнулся с следующим:
фантомное чтение наблюдается только на уровне READ UNCOMMITTED.
На READ COMMITTED его отследить уже не удается не смотря на все ухищрения.

Привожу модели на ваш суд. Может кто-то что-то скажет по данному поводу.

Система: MS SQL Server 2008 R2.
Снэпшот перед проведением опытов отключал:
ALTER DATABASE testdb SET READ_COMMITTED_SNAPSHOT OFF

Транзакция 1:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED; --хотя он и так стоит по умолчанию

BEGIN TRAN TR1;

	SELECT tovar, SUM(kolvo) as 'SUM' FROM T1 GROUP BY tovar; 
	GO
	
	WAITFOR DELAY '00:00:02'

	SELECT tovar, SUM(kolvo) as 'SUM' FROM T1 GROUP BY tovar;
	GO
	
	WAITFOR DELAY '00:00:06'

	SELECT tovar, SUM(kolvo) as 'SUM' FROM T1 GROUP BY tovar;
	GO

COMMIT TRAN TR1;


Транзакция 2:
BEGIN TRAN TR2;

	UPDATE T1 SET kolvo = 50 WHERE id=4;

	WAITFOR DELAY '00:00:05'
	
ROLLBACK TRAN TR2;


Логика. думаю, ясна: запускаем транзакцию 1 и получаем исходные данные;
сразу же запускаем вторую и проводим апдейт (в 1 транзакции небольшая задержка
чтоб разделить первую и вторую выборку), немножко ждем, откатываем апдейт
и снова считаем.
Согласно логики вопроса, мы должны были получить три значения: входное - измененное - входное.
Именно это мы наблюдаем на уровне READ UNCOMMITTED и должны наблюдать (согласно литературе)
и на READ COMMITTED. Но НЕ наблюдаем. Что ИМХО странно.
Хотелось бы услышать мнение опытных специалистов. Может кто-то что-то подобное проделывал.
6 окт 14, 00:07    [16664026]     Ответить | Цитировать Сообщить модератору
 Re: Фантомное чтение на Read Committed - есть или нет?  [new]
invm
Member

Откуда: Москва
Сообщений: 9646
На READ COMMITTED и выше грязного чтения не бывает.
6 окт 14, 00:50    [16664090]     Ответить | Цитировать Сообщить модератору
 Re: Фантомное чтение на Read Committed - есть или нет?  [new]
gandjustas
Member

Откуда:
Сообщений: 857
Блог
Alex Akopov,

Update вешает блокировку на изменение до конца транзакции, чтобы исключить грязное чтение. Поэтому ты не видишь в этом случае фантомов. Select висит пока транзакция с update не завершится.

Чтобы получить фантом надо сделать select с предикатом, в другой транзакции поменять запись, чтобы она начала удовлетворять предикату, и закоммитить, а в первой повторить выборку.
6 окт 14, 01:06    [16664120]     Ответить | Цитировать Сообщить модератору
 Re: Фантомное чтение на Read Committed - есть или нет?  [new]
Ruuu
Member

Откуда: Иркутск
Сообщений: 4272
Alex Akopov,

1. Вы пытаетесь воспроизвести не фантомное чтение, а неповторяющееся чтение. Для фантомного чтения во второй транзакции нужно заменить UPDATE на INSERT.
2. Для того чтобы воспроизвести неповторяющееся чтение UPDATE второй транзакции должен быть закомичен между селектами первой.
6 окт 14, 07:03    [16664294]     Ответить | Цитировать Сообщить модератору
 Re: Фантомное чтение на Read Committed - есть или нет?  [new]
Alex Akopov
Member

Откуда: Киев
Сообщений: 5
Спасибо всем за советы.

Просто замена Insert на Update во второй транзакции не принесла никаких изменений.
Но если вторую транзакцию закомитить сразу после него, то в результате действительно
получаем "исходное - обновленное - обновленное".
"Исходное - обновленное - исходное" я не получил, но фантом на лицо.
При включенном READ_COMMITTED_SNAPSHOT тоже.

Еще раз спасибо!

PS при включении SERIALIZABLE "эффект" пропадает.
6 окт 14, 11:27    [16664989]     Ответить | Цитировать Сообщить модератору
 Re: Фантомное чтение на Read Committed - есть или нет?  [new]
кириллk
Member

Откуда:
Сообщений: 1058
прост оставлю здесь


— READ_UNCOMMITTED — нефиксированное чтение. Этот уровень изоляции решает проблему «потерянного обновления», но при этом возможно получение разных результатов для одинаковых запросов без учета фиксации транзакции (возможна проблема «грязного чтения»). Это самый низкий уровень изоляции, используемый в СУБД, который обеспечивает максимальную параллельность работы.
— READ_COMMITTED — фиксированное чтение. Это уровень изоляции предотвращает проблему «грязного чтения», но позволяет получать разные результаты для одинаковых запросов в транзакции (сохраняется возможность «неповторяющегося чтения»);
— REPEATABLE_READ — повторяющееся чтение. Это уровень изоляции решает проблему «неповторяющегося чтения». На этом уровне сохраняется возможно выполнение операторов INSERT, приводящих к конфликтной ситуации «фантомная вставка». Этот уровень целесообразно использовать, если на выполняющиеся SQL-операторы не влияет добавление новых строк;
— SERIALIZABLE — последовательное выполнение. Третий уровень. Этот уровень гарантирует предотвращение всех описанных выше проблем параллельного доступа, но соответственно, наблюдается самая низкая степень параллелизма, так как обработка транзакций (с доступом к одним и тем же ресурсам) проводится только последовательно.

К сообщению приложен файл. Размер - 8Kb
6 ноя 14, 10:33    [16804738]     Ответить | Цитировать Сообщить модератору
 Re: Фантомное чтение на Read Committed - есть или нет?  [new]
кириллk
Member

Откуда:
Сообщений: 1058
кириллk,
Рассмотрим ситуации, в которых возможно возникновение данных проблем:

Потерянное обновление

Предположим, имеются две транзакции, открытые различными приложениями, в которых выполнены следующие SQL-операторы:
Транзакция 1 Транзакция 2
SELECT f2 FROM tbl1 WHERE f1=1; SELECT f2 FROM tbl1 WHERE f1=1;
UPDATE tbl1 SET f2=20 WHERE f1=1;
UPDATE tbl1 SET f2=25 WHERE f1=1;

В Транзакции1 изменяется значение поля f1, а затем в Транзакции2 также изменяется значение этого поля в той же таблице. В результате изменение, выполненное первой транзакцией, будет потеряно.
Строго говоря, суть проблемы заключается в том, что неизвестно, какой результат будет зафиксирован
в конечном итоге.

«Грязное» чтение

Если предыдущая проблема возникает при записи данных, то «грязное» чтение возможно, когда одна транзакция пытается прочитать данные, с которыми работает другая параллельная транзакция.
Предположим, имеется две транзакции, открытые различными приложениями, в которых выполнены следующие SQL-операторы:
Транзакция 1 Транзакция 2
SELECT f2 FROM tbl1 WHERE f1=1;
UPDATE tbl1 SET f2=f2+1 WHERE f1=1;
SELECT f2 FROM tbl1 WHERE f1=1;
ROLLBACK WORK;

В Транзакции1 изменяется значение поля f1, а затем в Транзакции2 выбирается значение поля f2. После этого происходит откат Транзакции 1. В результате значение, полученное второй транзакцией, будет отличаться от значения, хранимого в базе данных.
Строго говоря, здесь тоже проблема именно в непредсказуемости результата. Т. е. вторая транзакция может «успеть» считать необновленное значение, а может не успеть и получить обновленное.

Неповторяющееся чтение

Предположим, имеются две транзакции, открытые различными приложениями, в которых выполнены следующие SQL-операторы:
Транзакция 1 Транзакция 2
SELECT f2 FROM tbl1 WHERE f1=1; SELECT f2 FROM tbl1 WHERE f1=1;
UPDATE tbl1 SET f2=f2+1 WHERE f1=1;
SELECT f2 FROM tbl1 WHERE f1=1;

В Транзакции2 выбирается значение поля f2, затем в Транзакции1 изменяется значение поля f2. При повторной попытке выбора значения из поля f2 в транзакции 1 будет получен другой результат. Эта ситуация особенно неприемлема, когда данные считываются с целью их частичного изменения и обратной записи в базу данных.

Фантомное чтение

Предположим, имеется две транзакции, открытые различными приложениями, в которых выполнены следующие SQL-операторы:
Транзакция 1 Транзакция 2
SELECT SUM(f2) FROM tbl1;
INSERT INTO tbl1 (f1,f2) VALUES (15,20);
SELECT SUM(f2) FROM tbl1;

В Транзакции2 выполняется SQL-оператор, использующий все значения поля f2. Затем в Транзакции1 выполняется вставка новой строки, приводящая к тому, что повторное выполнение SQL-оператора в транзакции 2 выдаст другой результат. Такая ситуация называется фантомной вставкой и является частным случаем неповторяющегося чтения.


http://cascade-group.com.ua/1c-transaction-mssql/
6 ноя 14, 10:36    [16804755]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить