|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Здравствуйте. Заметил интересное поведение сервера отдаленно напоминающее ошибку: FB 2.5.5 Super x64, fbclient x32 из этого же дистрибутива, Win64, Delphi XE5, FIB 2 коннекта, у каждого по транзакции: isc_tpb_read_committed isc_tpb_rec_version isc_tpb_wait isc_tpb_lock_timeout Выполняется апдейт одной и той же записи (update t set f='NewValue' where Id=:pId), никакой обвязки на таблице, даже PK нет. tr1.Start tr2.Start update1.exec update2.exec Если последовательно - всё ожидаемо, update2 через 5 секунд вываливается с "Lock time-out on wait transaction. Deadlock. Update conflicts with concurrent update." А вот если коннекты разделены по потокам (коннект+транзакция+апдейт), и запустить потоки паралельно (очень паралельно, потоки привязанные к разным ядрам слушают один эвент и стартуют апдейт), жертва вылетает сразу (без ожидания 5 сек) вот так: "Deadlock. Update conflicts with concurrent update." Лечится установкой no_rec_version. В результате последовательно и паралельно работает одинаково (с ожиданием). Мне это кажется странным. wait должен или работать полностью в транзакциях с rec_version или не работать в таких транзакциях совсем. Пожалуйста, киньте тыц где это описано. Или объясните на пальцах где я не прав. P.S. Да, в реальном приложении такой ситуации (двойной паралельный апдейт одной записи) не возникнет, это тестовое приложение, оно эмулирует работу комплекса приложений в котором даже невозможное возможно. P.P.S. Да, я знаю, что супер 2.5 не очень SMP. Тестироваться будет и FB 3.0 и какой-нибудь MSSQL, просто начал с FB 2.5 как с самой знакомой платформы. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2016, 19:26 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Andrey_wait должен или работать полностью в транзакциях с rec_version или не работать в таких транзакциях совсем. Он и работает. Просто первый поток завершает транзакцию мгновенно и второй таки дожидается этого момента. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2016, 19:29 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Andrey_оно эмулирует работу комплекса приложений в котором даже невозможное возможно дабл_таблоид детектед :) ... |
|||
:
Нравится:
Не нравится:
|
|||
25.07.2016, 23:13 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Dimitry SibiryakovОн и работает.Мне кажется - нет. С rec_version поведение при паралельном исполнении и при последовательном отличается. А с no_rec_version поведение одинаковое. Если бы первывй поток "завершал транзакцию мгновенно", то поведение ни чем не отличалось бы от последовательного. Докдабл_таблоид детектед :) Не я такой, ТЗ такое :) Хотя это конечно не оправдание. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2016, 01:06 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Andrey_Мне кажется - нет. Когда кажется - надо включать аудит и изучать последовательность операций на сервере по нему. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2016, 11:41 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Dimitry SibiryakovКогда кажется - надо включать аудит и изучать последовательность операций на сервере по нему.А вот и спасибо, про вариант отладки с этой стороны я позабыл. На недельке займусь и отпишу тут. Пока меня устроит no_rec_version для update-транзакций. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2016, 12:07 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Решил таки доковырять проблему. Итого rec_version ведет себя таки адекватно - дожидаясь завершения блокирующей транзакции и после этого вываливаясь с исключением. Как при низком уровне паралельности, так и при высоком. Снимаю шляпу, был не прав. А вот с no_rec_version возникли вопросы. И, к сожалению, именно no_rec_version мне нужен будет в реальной системе. Или select for update, но это печально. В случае низкой паралельности запросов (кнопочками из двух приложений апдейты/комиты кормлю серверу) транзакция2 спокойно апдейтит запись, которую изменила транзакция1, после комита транзакции1. В случае высокой паралельности (паралельные потоки по ивенту отправляющие апдейты на одну запись) транзакция2 вылетает с "update conflicts with concurrent update" при комите транзакции1. И в логах сервера это подтверждается. Логи во вложении. P.S. Коннект по 127.0.0.1, по этому про плохую сеть даже не пофантазировать. P.P.S. тыц и тыц изучены. Первый тыц подтверждает мою теорию, но у меня такое даже на 2 транзакциях воспроизводится стабильно, а у товарища на 3. P.P.P.S. Я конечно это проверю и на FB 3.0, но если там поведение такое-же... мне остается только оборочивать апдейты в try...except в банальном тестовом приложении. А когда адепты MSSQL посмотрят в мой код и спросят "А зачем это у тебя так? Оно что, может свалиться?", я не буду знать что ответить. Такие дела. Жду Ваших комментариев :) ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2016, 17:16 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Andrey_И, к сожалению, именно no_rec_version мне нужен будет в реальной системе. http://www.gunsmoker.ru/2008/10/x-y-z.html detected Тебе надо не обрабатывать конфликты, а предотвращать их. А это требует определённой архитектуры как БД так и приложения. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2016, 17:22 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Dimitry SibiryakovТебе надо не обрабатывать конфликты, а предотвращать их. А это требует определённой архитектуры как БД так и приложения.Да... но нет. Во первых потому что такая разница в поведении - это ошибка. Во вторых потому что системы бывают не только новые, но и существующие. Причем существующие уже давно и, как следствие, имеющие очень высокую цену на изменение архитектуры. Пробежаться по коду и заменить X на Y легко, но сколько итераций полнофункционального тестирования для данного изменения будет, это болезненный вопрос. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2016, 17:46 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Andrey_Или select for update, но это печально.И что тут печального ? ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2016, 20:18 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
hvladAndrey_Или select for update, но это печально.И что тут печального ?Два запроса вместо одного. Ну, или хранимку апдейтящую на каждый чих, или холостой апдейт. И всё это вместо нативного no_rec_version. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2016, 21:06 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Чисто для ознакомления: http://www.sql.ru/forum/964534/hranimye-agregaty-bez-konfliktov-i-blokirovok-recept ... |
|||
:
Нравится:
Не нравится:
|
|||
26.07.2016, 21:19 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Dimitry SibiryakovЧисто для ознакомления: http://www.sql.ru/forum/964534/hranimye-agregaty-bez-konfliktov-i-blokirovok-recept Спасибо, познавательно, возможно после детального изучения куда-то и применю. Но не моя ситуация, у меня нет агрегатов и они не нужны. По крайне мере я пока не вижу куда их применить. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2016, 00:02 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Andrey_hvladпропущено... И что тут печального ?Два запроса вместо одного.EXEC BLOCK, если к процедурам аллергия PS в "проблему" не вникал ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2016, 01:41 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Andrey_не моя ситуация, у меня нет агрегатов Тогда как ты умудряешься получать update conflict? Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2016, 11:53 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
hvladAndrey_Два запроса вместо одного.EXEC BLOCK, если к процедурам аллергияВ целом те же яйца, что и процедура. В итоге при апдейте мне нужно просить сервер выполнить два запроса вместо одного. Всегда. Конечно с where current of это полтора запроса, а не два, но всеравно больше чем один. hvladPS в "проблему" не вникалИ это тоже печалит. Dimitry SibiryakovТогда как ты умудряешься получать update conflict? Псэудокоде Делфисайл Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
Параметры транзакций Код: sql 1. 2. 3. 4.
На релизе FB 3.0 (Super/SuperClassic) проверил - поведение не отличается. А после N-ого количества итераций теста при select из тестовой таблицы получил "database file appears corrupt (D:\DB\RDBTEST_3.0.FDB). wrong page type. page 177 is of wrong type (expected data, found unknown (89))." Сценария порчи базы не нашел. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2016, 12:50 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Andrey_Это то что я называю "высокий паралельность". Я это называю "крайний дебилизм". Ты мне по-простому, на пальцах объясни: вот лежит в БД "Иванов Иван Иванович" и внезапно один пользователь БД решил переименовать его в Петрова, а второй, так же внезапно, в ту же миллисекунду - в Сидорова. Вопрос: с какого перепою и кто им разрешил это делать? Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2016, 12:57 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Dimitry SibiryakovЯ это называю "крайний дебилизм". Ты мне по-простому, на пальцах объясни: вот лежит в БД "Иванов Иван Иванович" и внезапно один пользователь БД решил переименовать его в Петрова, а второй, так же внезапно, в ту же миллисекунду - в Сидорова. Вопрос: с какого перепою и кто им разрешил это делать? А... ну да, дибилизм. Когда в таблице одно поле, конечно дибилизм. Но иногда бывает, что в таблице больше одного поля, и один "пользователь" меняет одно поле, а другой другое поле. Конечно это всё решается, если разделить поля по разным таблицам связанным 1:1. Но это тот самый вопрос смены архитектуры существующей системы, который уже обсуждали. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2016, 13:09 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Andrey_один "пользователь" меняет одно поле, а другой другое поле. И опять возникает вопрос: с какого перепою и на каком основании? PS: И таки да, разведение этих полей по разным таблицам есть правильное действие, поскольку при ближайшем рассмотрении скорее всего окажется, что это аттрибуты разных сущностей. PPS: Для смены архитектуры существующей системы существует такая удобная вещь как view. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2016, 13:13 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov, +1 Andrey_ , ты можешь привести реальный пример когда это требуется, а не абстрактные размышления? ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2016, 13:13 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Andrey_В целом те же яйца, что и процедура. В итоге при апдейте мне нужно просить сервер выполнить два запроса вместо одного. Всегда. Конечно с where current of это полтора запроса, а не два, но всеравно больше чем один.Тебе шашечки, или ехать ? В конкурентном мире подходы не совпадают с последовательным, такова селяви. Собственно подходов два: 1. оптимистичный: прочитали, проверили - если подходит, пробуем взять себе, не получилось - повторяем 2. пессимистичный: захватили, потом проверяем SELECT WITH LOCK - как раз второй подход. Что выбрать - решать тебе. И вообще - с чего ты взял, что no_rec_version хоть как-то влияет на update ? Оно обещает (и делает) подождать при чтении (селекте), если тр-ция записи активна. Но никто не обещал делать этого при записи (апдейте). Andrey_На релизе FB 3.0 (Super/SuperClassic) проверил - поведение не отличается. А после N-ого количества итераций теста при select из тестовой таблицы получил "database file appears corrupt (D:\DB\RDBTEST_3.0.FDB). wrong page type. page 177 is of wrong type (expected data, found unknown (89))."А вот это я очень хотел бы воспроизвести. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2016, 14:25 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Dimitry SibiryakovИ опять возникает вопрос: с какого перепою и на каком основании?Симонов Денисты можешь привести реальный пример когда это требуется, а не абстрактные размышления? Реальный примерДано: Диспетчерская такси. У этой диспетчерской есть водители и заказы. У водителей есть смартфоны. С помощью приложений на смартфонах водители коммуницируют с диспетчерской. Сценарий: Водитель выполнил заказ и в приложении на смартфоне поставил галку "Свободен" Приложение со смартфона записало эту информацию в базу FB (через третье звено или на прямую - не важно) Каким-то волшебным образом (ведь в FB нельзя привязывать к ивентам идентификаторы) все подсистемы диспетчерской узнали что водитель выполнил заказ. И начинается карусель: Подсистема 1 выполняет поиск подходящего заказа для этого водителя и записывает ID заказа в запись водителя. Подсистема 2 выполняет перерасчет баланса водителя (и всякой другой фин.информации) и записывает ее в запись водителя. Подсистема 3 выполняет актуализацию геоданных водителя (полученных с того же смартфона) и записывает ее в запись водителя И в это же время асинхронно работают другие шедулеры выполняющие другие действия над водителями... А еще, перед тем как поставить галку "Свободен" водитель позвонил в диспетчерскую и попросил поставить его в какой-то сектор. И диспетчер ручками меняет запись водителя через свое приложение. Все эти действия происходят асинхронно. И любые 2 и более могут совпасть по времени. И да, это всё нужно паралелить, потому что это не более 20% от всей функциональности, а в пиковые моменты число заказов измеряется десятками в секунду Но! Но. В превую это может понадобится потому что работа под высокой нагрузкой и под низкой нагрузкой должна отличатся только временем отклика, но никак не сценарием поведения СУБД. Это делает СУБД предсказуемой. Dimitry SibiryakovPS: И таки да, разведение этих полей по разным таблицам есть правильное действие, поскольку при ближайшем рассмотрении скорее всего окажется, что это аттрибуты разных сущностей. PPS: Для смены архитектуры существующей системы существует такая удобная вещь как view.Да всё что угодно можно разделить, даже одну сущность по нескольким таблицам размазать, и даже может быстрее некоторые операции будут работать (записи то узкими станут). Правда другие операции станут гораздо медленнее. Потому что нужно будет или писать тригеры на вьюху (если с клиентов мы апдейтим вьюху) и в них проверять что же изменилось и делать соответствующие апдейты таблиц, или писать тригеры на таблицы (если мы с клиентов апдейтим таблицы а не вьюху) и в них собирать запись из кусков размазаных по разным таблицам чтобы проверить какое-то условие, поля которого "не относятся к данной сущности". Вопрос не в этом. hvladТебе шашечки, или ехать ?Мне ехать. Ехать так как работает no_rec_version при низкой нагрузке. hvladИ вообще - с чего ты взял, что no_rec_version хоть как-то влияет на update ? Оно обещает (и делает) подождать при чтении (селекте), если тр-ция записи активна. Но никто не обещал делать этого при записи (апдейте).Ну... не смотря на то что этого никто не обещал, по моим наблюдениям (которые подтверждаются логами сервера) и при апдейте влияет. rec_version - всегда дожидается своего таймаута/завершения конкурента. no_rec_version обычно дожидается завершения конкурента, но иногда вылетает сразу. hvladА вот это я очень хотел бы воспроизвести.На недельке повращаю базу по разному. Но ничего не обещаю. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2016, 15:10 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Andrey_Подсистема 1 выполняет поиск подходящего заказа для этого водителя и записывает ID заказа в запись водителя. Подсистема 2 выполняет перерасчет баланса водителя (и всякой другой фин.информации) и записывает ее в запись водителя. Подсистема 3 выполняет актуализацию геоданных водителя (полученных с того же смартфона) и записывает ее в запись водителя И в это же время асинхронно работают другие шедулеры выполняющие другие действия над водителями... с какого бодуна все эти подсистемы работают с одной таблицей? Это же разные сущности. Всегда считал что это ID водителя должно в заказ писаться, а не наоборот. Andrey_выполняет перерасчет баланса водителя (и всякой другой фин.информации) и записывает ее в запись водителя. а говорил агрегатов нет... ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2016, 15:19 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Andrey_Реальный пример И тут-то из всех щелей полезли балансы, текущий заказ и прочие хранимые агрегаты, которых "нет". Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2016, 15:20 |
|
Забавное поведение rec_version в wait-транзакциях
|
|||
---|---|---|---|
#18+
Господа, как вы на слово "баланс" то накинулись :) Повторюсь, у меня нет агрегатов и смысла в них не вижу. Считайте, что это не баланс, а количество выполненных заказов (банальный X=X+1). Так будет легче. Но, не спорю, для уменьшения конкуренции можно это всё складывать в отдельную табличку, а потом когда-нибудь ночью агрегировать. Но зачем? В случае баланса у меня нет конкурентных обновлений одного поля. И да, в водителе таки должен храниться заказ, т.к. способов назначить заказ водителю существует минимум 6 (всё что сходу вспомнил) и большинство из них могут конкурировать между собой. Поле это нужно чтобы конкуренты не перезаписали друг друга. Просто update Driver set OrderId=:pOrderId where DriverId=:pDriverId and OrderId is null ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2016, 15:36 |
|
|
start [/forum/topic.php?fid=40&msg=39281290&tid=1561953]: |
0ms |
get settings: |
11ms |
get forum list: |
12ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
45ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
58ms |
get tp. blocked users: |
1ms |
others: | 270ms |
total: | 413ms |
0 / 0 |