|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
Старые песни о главном. Промурыжил много тем и тут и в гугле, но общая картина складывается какая то странная. Чтобы не обсуждать абстрактно, приведу пример (вырожденный, потом обобщу) Есть таблица остатков (скажем денсредств) и 2 потока каждый из которых читает: SELECT sum FROM account WHERE key = 5, допустим сумма равна 3-м, на сервере приложений добавляет к 3, свою сумму, скажем первый добавляет 2, второй добавляет 3, и пытается записать результат UPDATE account SET sum = result WHERE key=5. (правильный ответ, если что : 3+2+3 = 8). Предположим они идут параллельно, первый считал - второй считал - первый записал - второй записал. Итак что будут делать (по умолчанию (!)) с repeatable read каждая из СУБД: 1. MS SQL на сколько я понимаю на первое чтение будет 3 и повесит S блокировку, на второе чтение будет 3 и повесит S блокировку - на первой записи значения 5 попытается конвертить S блокировку в X и повиснет, так как на втором чтении висит S блокировка, на второй записи значения 6 попытается конвертить S в X, также повиснет, после чего один из процессов пометится как deadlock (допустим 2-й), кинет exception, и попросит сервер приложений повторить 2-ю транзакцию, в итоге сначала запишется 5, при повторе запишется 8 все ОК. 2. PostgreSQL и Firebird - первое чтение будет 3, второе чтение будет 3, первая запись будет 5 и пройдет, вторая запись увидит что значение изменилось с начала транзакции и кинет exception, и "попросит" сервер приложений повторить, тот заново начнет транзакцию и запишет 8 - все ОК. 3. Самое веселое в Oracle, который как я понимаю сначала запишет 5, а потом запишет 6 и будет думать что все ОК. Хотя это не так. Теперь замечания: a) я так понимаю для 2 и 3 можно повторять поведение 1 при помощи SELECT FOR UPDATE, правда там будет U блокировка, то есть уже второе чтение повиснет и предотвратит deadlock, ну или SELECT FOR SHARE - тогда поведение будет точь в точь как в пункте 1. б) у 1 я так понимаю без "ручной" работы с timestamp'ом повторить 2-е поведение автоматически нет возможности. Хотя как я понимаю нет особой разницы какой exception будет deadlock или update conflict (я так понимаю второй все же чаще бывает, но ресурсы на блокировки зато не тратятся) в) у 3 я так понимаю можно включить TIL SERIALIZABLE и он тогда будет вести себе как 1 или как SELECT FOR UPDATE в пункте а) Понимаю что где-то заблуждаюсь (а может и везде), поэтому и спрашиваю в каком пункте я не прав. ЗЫ: Да, я в курсе что UPDATE account SET sum = sum + 2 WHERE key = 5, UPDATE account SET sum = sum + 3 WHERE key = 5, даже при READ COMMITED дадут 8 (кстати во втором случае да или нет?), но тут вопрос что вычисление может быть сложнее, требовать что-то еще чем просто суммирование, поэтому этот пример привел чтобы не усложнять. И еще такой вопрос: Если есть SELECT x FROM t1 LEFT JOIN (SELECT SUM(f),j FROM t2 GROUP BY j) Q ON Q.j = t1.x, в блокировочниках (и SELECT FOR UPDATE), S-блокироки повесятся на всю таблицу t2, или только на те у которых j из таблицы t1. Потому как это получается зависит от построенного плана выполнения, если решит сделать predicate push down - блокировки будут только на нужные данные, если нет то на всю таблицу? ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 12:41 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
студент учи что такое транзакции, ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 15:47 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
ScareCrowстудент учи что такое транзакции, Очень ценное замечание. Чтобы я без него делал даже не знаю... ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 15:57 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
Логика железная, кстати. Вспоминаю "Ералаш", там где 13*7=28. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 16:00 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
Кстати если кто не понял расширю процесс: первый начал транзакцию - второй начал транзакцию - первый считал - второй считал - первый записал - второй записал - первый коммитнул транзакцию - второй коммитнул транзакцию ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 16:01 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
Мимо пробегал...Логика железная, кстати. Вспоминаю "Ералаш", там где 13*7=28. Еще одно ценное замечание. Очень полезный форум. Надо почаще писать :) ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 16:03 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
авторб) у 1 я так понимаю без "ручной" работы с timestamp'ом повторить 2-е поведение автоматически нет возможности. Хотя как я понимаю нет особой разницы какой exception будет deadlock или update conflict (я так понимаю второй все же чаще бывает, но ресурсы на блокировки зато не тратятся) Неправильно понимаете. У 1 версионный режим существует аж с 2005 года. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 17:26 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
pkarklinавторб) у 1 я так понимаю без "ручной" работы с timestamp'ом повторить 2-е поведение автоматически нет возможности. Хотя как я понимаю нет особой разницы какой exception будет deadlock или update conflict (я так понимаю второй все же чаще бывает, но ресурсы на блокировки зато не тратятся) Неправильно понимаете. У 1 версионный режим существует аж с 2005 года. Это да, я уже тоже заметил... А он как 3 или как 2 работает? В смысле кидает update conflict exception или просто перезаписывает (ну или там минимум \ максимум и т.п. как в oracle strams)... ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 17:42 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
Nitro_Junkie, Transactions running under snapshot isolation take an optimistic approach to data modification by acquiring locks on data before performing the modification only to enforce constraints. Otherwise, locks are not acquired on data until the data is to be modified. When a data row meets the update criteria, the snapshot transaction verifies that the data row has not been modified by a concurrent transaction that committed after the snapshot transaction began. If the data row has been modified outside of the snapshot transaction, an update conflict occurs and the snapshot transaction is terminated. The update conflict is handled by the Database Engine and there is no way to disable the update conflict detection. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 17:55 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
pkarklinNitro_Junkie, Transactions running under snapshot isolation take an optimistic approach to data modification by acquiring locks on data before performing the modification only to enforce constraints. Otherwise, locks are not acquired on data until the data is to be modified. When a data row meets the update criteria, the snapshot transaction verifies that the data row has not been modified by a concurrent transaction that committed after the snapshot transaction began. If the data row has been modified outside of the snapshot transaction, an update conflict occurs and the snapshot transaction is terminated . The update conflict is handled by the Database Engine and there is no way to disable the update conflict detection. То есть я так понимаю работает как 2? Тогда зачет мелкософту :) ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:04 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
Nitro_Junkie, Правда как 3 он работать не умеет, судя по фразе автор there is no way to disable the update conflict detection Другое дело зачем oracle так резолвит update conflict'ы мне не до конца понятно. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:05 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
а как вы предлагаете их резолвить при оптимистичной блокировке? ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:17 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
ScareCrowа как вы предлагаете их резолвить при оптимистичной блокировке? ну постгря же подругому резолвит, причем тоже оптимистически ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:22 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
ScareCrowа как вы предлагаете их резолвить при оптимистичной блокировке? Кидать exception. Ну иметь этот вариант точно, потому как просто всегда записывать последнее это жесть... ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:23 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
ScareCrowа как вы предлагаете их резолвить при оптимистичной блокировке? в Firebird/InterBase, в версионнике, snapshot может попытаться поменять измененные с момента его стартат данные, только если они были отменены по rollback. То есть, Tran1 - snapshot start Tran2 - update X Tran1 - update X - получаем lock conflict Если Tran2 сделает Rollback, то Tran1 может повторить update Если Tran2 сделает Commit, то Tran1 эту запись не обновит в принципе, потому что она "не видит" изменения , сделанного Tran2, в силу своего уровня изолированности. А раз не может видеть (видит только то, что было до действий Tran2), значит не может и изменить. И перешибать значение 3 на что-то свое, зная, что там уже это значение изменено и закоммичено - как бы моветон. Snapshot это как бы snapshot и есть. Другое дело, что стандартный RepeatableRead позволяет видеть фантомы... ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:27 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
автортолько если они были отменены по rollback. эм? если что то Rollback - то этого как бы и нет. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:29 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
и насколько я помню Firebird там это возможно только если указать wait у транзакции. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:29 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
Ivan DurakScareCrowа как вы предлагаете их резолвить при оптимистичной блокировке? ну постгря же подругому резолвит, причем тоже оптимистически эм? http://www.postgresql.org/docs/9.3/static/transaction-iso.html авторIf the first updater rolls back, then its effects are negated and the repeatable read transaction can proceed with updating the originally found row. But if the first updater commits (and actually updated or deleted the row, not just locked it) then the repeatable read transaction will be rolled back with the message ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:32 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
kdvScareCrowа как вы предлагаете их резолвить при оптимистичной блокировке? в Firebird/InterBase, в версионнике, snapshot может попытаться поменять измененные с момента его стартат данные, только если они были отменены по rollback. То есть, Tran1 - snapshot start Tran2 - update X Tran1 - update X - получаем lock conflict Если Tran2 сделает Rollback, то Tran1 может повторить update Если Tran2 сделает Commit, то Tran1 эту запись не обновит в принципе, потому что она "не видит" изменения , сделанного Tran2, в силу своего уровня изолированности. А раз не может видеть (видит только то, что было до действий Tran2), значит не может и изменить. И перешибать значение 3 на что-то свое, зная, что там уже это значение изменено и закоммичено - как бы моветон. Snapshot это как бы snapshot и есть. Другое дело, что стандартный RepeatableRead позволяет видеть фантомы... Кстати да в, описанном мной примере, update conflict кидается не сразу, а по завершении 1-й транзакции, в надежде что эта транзакция rollback'ся хотя это как-то ИМХО чересчур оптимистично (в среднем процент rollback'ых транзакций не сильно большой), можно было бы и сразу кинуть. Я просто опустил этот момент, чтобы не усложнять ситуацию, и считал что транзакция начинается при первом чтении и коммитится сразу после записи. А что касается фантомов, то, по идее, можно придумать (правда мегаизвращенный случай) когда его и в serializable'е можно получить. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:34 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
ScareCrowIvan Durakпропущено... ну постгря же подругому резолвит, причем тоже оптимистически эм? http://www.postgresql.org/docs/9.3/static/transaction-iso.html авторIf the first updater rolls back, then its effects are negated and the repeatable read transaction can proceed with updating the originally found row. But if the first updater commits (and actually updated or deleted the row, not just locked it) then the repeatable read transaction will be rolled back with the message Чего же вы дальше не процитировали?: But if the first updater commits (and actually updated or deleted the row, not just locked it) then the repeatable read transaction will be rolled back with the message ERROR: could not serialize access due to concurrent update because a repeatable read transaction cannot modify or lock rows changed by other transactions after the repeatable read transaction began. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:36 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
ScareCrowнасколько я помню Firebird там это возможно только если указать wait у транзакции. Точнее если не указать no wait, поскольку wait это режим по умолчанию. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:37 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov, Так все таки, а в Оракле что обычно делают? SERIALIZABLE включают? Ручные блокировки FOR UPDATE используют? Смотрят на системную колонку версии ряда ? ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:46 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
Nitro_JunkieТак все таки, а в Оракле что обычно делают? Говорят "фу, что это у вас за update conflict-ы, у нас вот такого дерьма нет". Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:51 |
|
Конфликт записи \ чтения
|
|||
---|---|---|---|
#18+
Dimitry SibiryakovNitro_JunkieТак все таки, а в Оракле что обычно делают? Говорят "фу, что это у вас за update conflict-ы, у нас вот такого дерьма нет". :) . А если серьезно? Им что жалко было такой режим сделать, для версионника это же не проблема? С учетом : Oracle has chosen the harder-to-implement but infinitely more concurrent multi-versioning scheme. ЗЫ: Правда при этом описание repeatable read прерывается, а до этого были только лучи ненависти к deadlock'а. И нигде описание что oracle будет делать в том случае, когда блокировочник кинет deadlock. Пойти что ли на oracle'овски подфорум, или меня там ногами запинают? :) ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2013, 18:58 |
|
|
start [/forum/topic.php?fid=35&fpage=7&tid=1552413]: |
0ms |
get settings: |
9ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
35ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
87ms |
get tp. blocked users: |
2ms |
others: | 28ms |
total: | 198ms |
0 / 0 |