30.09.2008, 00:29 | #1 |
----------------
|
Ax3sp3 vs Ax4sp2 на примере
Решил зафиксировать результаты небольших опытов, проведенных на приложениях Ax3sp3 и Ax4sp2 подключенных к серверу MS SQL2005 с БД в режиме 90.
В опытах принимают участие: табличка aTable с полями Id - int с уникальным индексом Value - int без индекса и 2 жобика X++: static void Job_b1(Args _args) { aTable aTable; ; ttsbegin; aTable = aTable::find(12, true); // такая запись есть aTable.Value = timenow(); aTable.update(); ttscommit; } static void Job_b2(Args _args) { aTable aTable; ; select aTable where aTable.Value == 200; // такой записи нет ttsbegin; select aTable where aTable.Value == 200; aTable = aTable::find(12, true); aTable.Value = timenow(); aTable.update(); ttscommit; } Запускаем 2 клиента аксапты. В одном из них ставим точку останова на строке aTable.update(); первого джобика и выполняем. Во втором выполняем джобик2 по шагам. Ax3sp3 - джобик2 вешается на строке aTable = aTable::find(12, true); до тех пор пока не закончится джоб1. Ax4sp2 - джоб2 отрабатывает до конца, однако при попытки продолжить джоб1 получаем ошибку: Невозможно отредактировать запись в aTable (aTable). Возник конфликт обновления из-за того, что другой пользовательский процесс выполняет удаление записи или изменение одного или нескольких полей в записи. Опыт 2 Запускаем 2 клиента аксапты. В одном из них ставим точку останова на строке ttscommit; первого джобика и выполняем. Во втором выполняем джобик2 по шагам. Ax3sp3 - на этот раз джобик2 вешается на строке select aTable where aTable.Value == 200; (которая после ttsbegin) до тех пор пока не закончится джоб1. Ax4sp2 - теперь и здесь джоб2 вешается, но на строке aTable.update(); до тех пор пока не закончится джоб1, а потом выдает туже ошибку: Невозможно отредактировать запись в aTable (aTable). Возник конфликт обновления из-за того, что другой пользовательский процесс выполняет удаление записи или изменение одного или нескольких полей в записи. Последний раз редактировалось Wamr; 30.09.2008 в 00:33. |
|
30.09.2008, 07:56 | #2 |
Участник
|
а вывод какой?
|
|
30.09.2008, 10:23 | #3 |
Участник
|
|
|
30.09.2008, 10:40 | #4 |
MCTS
|
Для полноты картины можно скачать проектик отсюда и из третьего клиента посмотреть, какие ресурсы блокирует SQL сервер при выполнении каждой строки джобиков.
А еще лучше и проще почитать документацию по 4-ке |
|
30.09.2008, 10:41 | #5 |
Участник
|
То есть ты хочешь сказать, что точка останова влияет на исполнение запроса?
Что-то слабо верится... Но попробую на досуге |
|
30.09.2008, 10:44 | #6 |
Участник
|
Цитата:
Блокировка на странице индекса оказалась ? А откуда ей взяться ? Ведь уровень изоляции транзакции ReadCommited, а не Serialized. Блокировки по строке не должно быть - записи то нет. Либо возможно блокировка легла на страницу или таблицу. |
|
30.09.2008, 10:46 | #7 |
Участник
|
Цитата:
Там просто точкой останова регулируется, проходил update строки или нет. Соответственно разное поведние 4-ки и 3-ки. Табличка кстати, судя по поведению, настроена на оптимистическую модель конкуренции. Последний раз редактировалось Logger; 30.09.2008 в 11:19. |
|
30.09.2008, 10:56 | #8 |
Участник
|
Из приведенного описания можно сделать такие выводы:
Ax3sp3 Внутри открытой транзакции все запросы, по умолчанию, не явно, добавляют хинт forupdate и блокируют считываемую запись Ax4sp2 Либо криво написан метод aTable::find(), либо не работает настройка aTable.selectForUpdate(_update);. |
|
30.09.2008, 11:13 | #9 |
Участник
|
Попробовал на Ax3KR3 Oracle 9
1-й опыт - все как описано. 2-й опыт - повис во 2-м джобе на X++: aTable = aTable::find(12, true); Оракл рулит ! Интересно, а как с этим экспериментом в SQL2008 ? |
|
30.09.2008, 11:16 | #10 |
Участник
|
Сомнительно (автор указал что записи со значением 200 - нет - если блокировка на запись накладывается, то блокироваться нечему). Скорее там блокировка лишняя накладывается где-то, напрмер на страницу или таблицу. А реально надо смотреть на сервак что происходит. К сожалению нет под рукой SQL2005
Последний раз редактировалось Logger; 30.09.2008 в 11:36. |
|
30.09.2008, 14:17 | #11 |
Участник
|
1. В методах find на таблицах часто используется конструкция:
X++: ... myTable.SelectForUpdate(update); select myTable where myKey = key; ... В Ax3sp3 : при выполнении сразу блокируется запись (страница, таблица) на обновление, т.е. в запросе на SQL сервер присутствует хинт UPDLOCK. В Ax4sp2 : такой блокировки не происходит. 2. В Ax3sp3, при настройках по умолчанию, вне транзакции используется грязное чтение (READ UNCOMMITED), а внутри чистое (READ COMMITED) В Ax4sp2 : используется только чистое чтение (READ COMMITED) |
|
30.09.2008, 14:38 | #12 |
Участник
|
|
|
|
За это сообщение автора поблагодарили: Wamr (-1). |
01.10.2008, 00:51 | #13 |
----------------
|
Сергей,
выводы каждый может сделать сам, мне показался интересным результат, который я и положил в общий доступ, так чтобы можно было перечитывать и думать... в свободное время Logger, именно SP3 (без KR3) поиск по неиндексированому полю = TableScan, а значит и подвисание на заблокированной строке при уровне изоляции ReadCommited CDR, спасибо, но мне пока и sp_lock хватает Иван, уровень блокировки на строку поднимается до эксклюзивного после выполнения update Владимир, я бы сказал, что в ax3sp3, запрос выполненный за пределами транзакции равноценен запросу в транзакции с хинтом selectLocked(false), то бишь NOLOCK Это можно назвать одним из выводов Отключение OCC на таблице делает ax4sp2 похожим на ax3sp3+Oracle9, а не ax3sp3+SQL2005 |
|
09.10.2008, 23:12 | #14 |
----------------
|
продолжение
Проверил AX4sp2 с отключённым OCC.
Опыт 1 + Опыт 2 джобик2 вешается на строке aTable = aTable::find(12, true); до тех пор пока не закончится джоб1. Аналогично себя ведет Ax3sp3 с Oracle9 и Ax3sp3 с SQL2005 при включении на БД snapshot isolation (не тестированное сочетание) |
|
Теги |
производительность, ax3.0, ax4.0 |
|
|