Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Чем принципиально отличается ...
|
|||
|---|---|---|---|
|
#18+
Народ ! Чем принципиально отличаются следующие два фрагмента кода: ... ПЕРВЫЙ SET TRANSACTION ISOLATION LEVEL SERIALIZABLE BEGIN TRANSACTION SELECT @CUSTID = MAX(CUSTID) FROM CUSTOMERS SET @CUSTID = @CUSTID+1 INSERT INTO CUSTOMERS (CUSTID, ...) VALUES (@CUSTID, ...) COMMIT ... ВТОРОЙ BEGIN TRANSACTION SELECT @CUSTID = MAX(CUSTID) FROM CUSTOMERS WITH (TABLOCKX) SET @CUSTID = @CUSTID+1 INSERT INTO CUSTOMERS (CUSTID, ...) VALUES (@CUSTID, ...) COMMIT Надо ли в первом примере включать WITH (TABLOCKX) в SELECT ? В чем тонкость и как это работает ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.07.2001, 18:00 |
|
||
|
Чем принципиально отличается ...
|
|||
|---|---|---|---|
|
#18+
Ответ следующий. В SQL Server нет before image log'a, след., нет (на данный момент) того, что иногда (хотя это неправильно) называется versioning, когда каждому клиенту на период транзакции дается собственный snapshot данных на момент ее начала без оглядки на то, что другие за время ее работы с этими данными сделают. Поэтому чтобы обеспечить целостность Вашего max(ID) попытка добавить большее значение другими сессиями будет просто блокирована, пока не отработает первая транзакция. С этой точки зрения разницы между предложенными вариантами нет. Желающие добавить ID, больше максимального, в любом случае будут ждать. С другой стороны, если Вы посмотрите на блокировки, то увидите, что первый вариант блокирует key range, начиная c ключa записи с max(ID) и выше. Собственно, serializable в SQL Server так и делается, и пока таких блокировок не было (6.5 и ранее) он вообще не делал разницы между repeatable read и serialaizable. Второй вариант, очевидно, блокирует всю таблицу, и вынуждает ждать добавление любой записи, а не только большей max(ID). Поэтому первый предпочтительнее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.07.2001, 03:56 |
|
||
|
Чем принципиально отличается ...
|
|||
|---|---|---|---|
|
#18+
Спасибо ! Извиняюсь за назойливость, но хотелось бы внести ясность правильно ли я понял Ваш ответ Если правильно понял, то второй вариант блокирует ВСЮ таблицу до конца транзакции и доступ к таблице для ЛЮБЫХ действий из других сессий закрыт. ЭТО ЖЕСТКО, ТУПО и ПОНЯТНО. >>>>Первый способ предпочтительней ! А на счет первого способа не совсем ясен МЕХАНИЗМ. То есть, как я понял из Вашего ответа, из других сессий доступ к таблице будет получен, причем для любых операций (SELECT, UPDATE, DELETE) но только если используемая выборка из таблицы не затрагивает записи с CUSTID больше "текущего максимального для открытой транзакции" и следовательно запрос SELECT @CUSTID = MAX(CUSTID) FROM CUSTOMERS будет сериализован, т.е. другими словами поставлен в очередь, но в тоже время не ясно, что будет в таком случае: Предположим, что в таблице есть три записи с CUSTID = 1, 2, 3 из одной сессии выполняется запрос (в контексте вышеизложенного) SELECT @CUSTID = MAX(CUSTID) FROM CUSTOMERS, а из другой UPDATE CUSTOMERS SET CUSTID = 5 WHERE CUSTID = 1. С точки зрения здравого смысла - бред конечно, но с теоретической точки зрения ОЧЕНЬ ИНТЕРЕСНО И НЕ ПОНЯТНО И еще вопрос в продолжении темы: А если такой кусок кода находится в теле хранимой процедуры назовем ее TESTPROC и первым оператором этой процедуры будет SET XACT_ABORT ON. Далее есть еще одна процедура EXAMPROC и в ней идет вызов этой процедуры ... BEGIN TRANSACTION ... EXEC TESTPROC IF @@ERROR <> 0 BEGIN ... END ELSE BEGIN ... END ... Будет ли установлено @@ERROR <> 0 при возникновении RUNTIME ERROR в TESTPROC после выхода из процедуры TESTPROC или из EXAMPROC вылетим сразу после возникновения этой ошибки в TESTPROC с откатом внешней и всех внутренних транзакций ? Заранее благодарен за детальный ответ ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.07.2001, 12:50 |
|
||
|
Чем принципиально отличается ...
|
|||
|---|---|---|---|
|
#18+
>но в тоже время не ясно, что будет в таком случае: ... Все обновляющие транзакции, норовящие модифицировать все, что >=3, будут ждать. Это как раз понятно и неинтересно. >Будет ли установлено @@ERROR <> 0 при возникновении RUNTIME ERROR в TESTPROC ... Нет, не будет. То, что нужные ей данные блокированы, ошибкой не является. SET XACT_ABORT откатывает транзакцию при возникновении ошибки, а не вызывает ошибку при откате. Я Вам советую ради интереса поставить SQL Server, п.ч. абстрактное изучение документации без экспериментов мало что дает. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 15.07.2001, 01:29 |
|
||
|
Чем принципиально отличается ...
|
|||
|---|---|---|---|
|
#18+
>>Я Вам советую ради интереса поставить SQL Server, п.ч. абстрактное изучение >>документации без экспериментов мало что дает. SQL Server стоит (Personal Edition 7.0 SP2), так что это не совсем абстрактное изучение Но вот что странно, кусок №1 не работает, т.е. работает не корректно. Я открыл две сессии в QA и запустил кусок №1 с небольшой модификацией: SET TRANSACTION ISOLATION LEVEL SERIALIZABLE BEGIN TRANSACTION SELECT @CUSTID = MAX(CUSTID) FROM CUSTOMERS SET @CUSTID = @CUSTID+1 WAITFOR DELAY '00:00:02' INSERT INTO CUSTOMERS (CUSTID, ...) VALUES (@CUSTID, ...) COMMIT в одной сессии и без WAITFOR DELAY '00:00:02' в другой сессии, на пол секунды позже чем в первой. Так вот в той сессии где без WAITFOR все завершилось успехом без какого либо ожидания разблокировки таблицы, а в сессии с WAITFOR DELAY '00:00:02' произошла ошибка (дублирование перв. ключа) ????? ПОЛУЧАЕТСЯ, ЧТО [SET TRANSACTION ISOLATION LEVEL SERIALIZABLE] - работает "несколько" не так, как мы думаем ???? Напротив, если использовать WITH (TABLOCKX) и провести тот же тест с WAITFOR DELAY '00:00:02' то все работает корректно, но как уже говорилось Вами и я с этим согласен, это как то некрасиво и неэффективно ( КАК ЖЕ ВСЕ ТАКИ ПРАВИЛЬНО ??? ============================= А по поводу @@Error я не это имел в виду (то что Вы написали - очевидно) При тесте оказалось, что с @@Error СОВСЕМ НЕ ПОЛУЧАЕТСЯ РАБОТАТЬ(ОБРАБОТАТЬ), т.к. при возникновении RUNTIME ERROR и установленном SET XACT_ABORT ON происходит вылет ============= из всех вложенных процедур на самый верхний уровень, другими словами если из QA запустить PROC1 из которой вызывается PROC2 из которой вызывается PROC3 и т.д. то при ран-тайм ошибке в PROC3 - вылетаем в QA и ни в PROC2, ни в PROC1 нет возможности среагировать на ошибку и как то это обработать (((((((((( Получается вывод: Для нормальной обработки ошибок пользоваться SET XACT_ABORT ON - нельзя. А в BOL пишут, что такой режим очень рекомендуется :-8 И на последок еще один вопрос. Если все таки пользовать WITH (TABLOCKX) то надо ли его писать один раз или несколько раз, если делается запрос с вложенным запросом на ту же самую таблицу ? Например: ... SET IDENTITY_INSERT Products ON SELECT @nextidentval = MIN(IDENTITYCOL) + IDENT_INCR('Products') FROM Products with (TABLOCKX) o WHERE IDENTITYCOL BETWEEN IDENT_SEED('Products') AND 2147483647 AND NOT EXISTS (SELECT * FROM Products with (TABLOCKX) oo WHERE oo.IDENTITYCOL = o.IDENTITYCOL + IDENT_INCR('Products')) SET IDENTITY_INSERT Products OFF И еще, как быть со штуками типа IDENT_SEED('xxx'), IDENT_INCR('xxx') - ведь это тоже по сути обращения к таблице (или к схеме) ? P.S. Не хочу надоедать с надоевшей всем темой, но все таки мне это надо не для праздного любопытства, а для конкретного дела и очень хочется сделать КАЧЕСТВЕННО, ГРАМОТНО и ПРОФЕССИОНАЛЬНО вот такие дела ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.07.2001, 21:09 |
|
||
|
Чем принципиально отличается ...
|
|||
|---|---|---|---|
|
#18+
2 Kapik Мне неохота сейчас залезать в дебри уровней изоляции в SQL Server, но из Вашего вопроса мне показалось, что Вы хотите сами наращивать значение некоего счетчика и идете по пути нахождения максимального значения и прибавления ему единицы. Если я прав в своем предположении, то посоветовал бы Вам задуматься кроме как над блокировками (проблема получения действительно максимального значения), еще и над тем, какие у Вас будут таймауты у юзеров, ежели таблица разрастется, да даже если и не разрастется ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.07.2001, 05:48 |
|
||
|
Чем принципиально отличается ...
|
|||
|---|---|---|---|
|
#18+
SET IDENTITY_INSERT Products ON SELECT @nextidentval = MIN(IDENTITYCOL) + IDENT_INCR('Products') FROM Products with (TABLOCKX) o WHERE IDENTITYCOL BETWEEN IDENT_SEED('Products') AND 2147483647 AND NOT EXISTS (SELECT * FROM Products with (TABLOCKX) oo WHERE oo.IDENTITYCOL = o.IDENTITYCOL + IDENT_INCR('Products')) SET IDENTITY_INSERT Products OFF Дырки заполнять хотите? А стоит ли овчинка выделки, иначе говоря а зачем это Вам надо? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.07.2001, 05:51 |
|
||
|
Чем принципиально отличается ...
|
|||
|---|---|---|---|
|
#18+
Если предыдущее предположение верно, то посмотрите http://www.osp.ru/win2000/sql/2001/04/865.htm ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.07.2001, 08:25 |
|
||
|
Чем принципиально отличается ...
|
|||
|---|---|---|---|
|
#18+
За ссылку на статью Павлу - спасибо. Статья интересная, но у меня используется SQL Server 7.0 (SP2) и UDF там нет Но общий принцип ясен можно будет воспользоваться. >>Мне неохота сейчас залезать в дебри уровней изоляции в SQL Server, но из Вашего вопроса мне показалось, что Вы >>хотите сами наращивать значение некоего счетчика и идете по пути нахождения максимального значения и прибавления ему >>единицы. Если я прав в своем предположении, то посоветовал бы Вам задуматься кроме как над блокировками (проблема >>получения действительно максимального значения), еще и над тем, какие у Вас будут таймауты у юзеров, ежели таблица >>разрастется, да даже если и не разрастется ДЕЛО НЕ В СПОСОБАХ НУМЕРАЦИИ ID (С ЗАПОЛНЕНИЕМ ДЫРОК ИЛИ БЕЗ), меня как раз интересуют вопросы работы БЛОКИРОВОК и уровни изоляции ТРАНЗАКЦИЙ. Как я писал выше WITH (TABLOCKX) и SET TRANSACTION ISOLATION LEVEL SERIALIZABLE - это две большие разницы. Но пользовать WITH (TABLOCKX) при разросшейся таблице - это обречь пользователей на постоянные ожидания (наверное это так). Вывод получается такой: НАДО ПРИДУМЫВАТЬ СПЕЦИФИЧЕСКИЕ АЛГОРИТМЫ ДЛЯ РАСЧЕТА [ID] (как в вышеупомянутой статье), КОТОРЫЕ ПОЗВОЛЯЛИ БЫ НЕ БЛОКИРОВАТЬ ВСЮ ОСНОВНУЮ ТАБЛИЦУ, А БЛОКИРОВАТЬ ЕЕ (ТАБЛИЦЫ) ЧАСТЬ, ЛИБО БЛОКИРОВАТЬ НЕКУЮ НЕБОЛЬШУЮ ВСПОМОГАТЕЛЬНУЮ ТАБЛИЦУ, ИСПОЛЬЗУЕМУЮ ДЛЯ РАСЧЕТА [ID]. И вот мы подошли к сути вопроса: КАК НЕ ПОЛЬЗУЯСЬ WITH (TABLOCKX) КОРРЕКТНО ЗАБЛОКИРОВАТЬ ЧАСТЬ ТАБЛИЦЫ, (НАПРИМЕР ПО УСЛОВИЮ НА ИНДЕКС) ??? Ведь SET TRANSACTION ISOLATION LEVEL SERIALIZABLE - не работает так как ожидалось (тогда ЗАЧЕМ ЭТО ВООБЩЕ НУЖНО И ГДЕ ПРАКТИЧЕСКИ ПРИМЕНЯЕТСЯ ???). Как же все таки быть, как правильно и эффективно ???????? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.07.2001, 13:04 |
|
||
|
Чем принципиально отличается ...
|
|||
|---|---|---|---|
|
#18+
>Как я писал выше WITH (TABLOCKX) и SET TRANSACTION ISOLATION LEVEL SERIALIZABLE - это две большие разницы. Умгу, и в BOL это описано, не понял в чем проблема. >Вывод получается такой: НАДО ПРИДУМЫВАТЬ СПЕЦИФИЧЕСКИЕ АЛГОРИТМЫ ДЛЯ РАСЧЕТА [ID] Зачем интересно? Мне пришлось использовать подход описанный в статье только раз, да и то только из за специфичности задачи. А Вам зачем? >И вот мы подошли к сути вопроса: КАК НЕ ПОЛЬЗУЯСЬ WITH (TABLOCKX) КОРРЕКТНО ЗАБЛОКИРОВАТЬ ЧАСТЬ ТАБЛИЦЫ, Опять вопрос - зачем? В чем смысл этой блокировки, что она Вам дает? >Ведь SET TRANSACTION ISOLATION LEVEL SERIALIZABLE - не работает так как ожидалось Ожидалось кем? И как эта установка по Вашему должна работать? Ключевой Ваш вопрос - ЗАЧЕМ ЭТО ВООБЩЕ НУЖНО И ГДЕ ПРАКТИЧЕСКИ ПРИМЕНЯЕТСЯ ??? Бывает, что нужно использовать эти установки, но такая необходимость возникает крайне редко, во всяком случае я даже с ходу и пример придумать не могу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.07.2001, 13:21 |
|
||
|
Чем принципиально отличается ...
|
|||
|---|---|---|---|
|
#18+
2 Genady >Как я писал выше WITH (TABLOCKX) и SET TRANSACTION ISOLATION LEVEL SERIALIZABLE - это две большие разницы. >>Умгу, и в BOL это описано, не понял в чем проблема. >Ведь SET TRANSACTION ISOLATION LEVEL SERIALIZABLE - не работает так как ожидалось >>Ожидалось кем? И как эта установка по Вашему должна работать? В BOL это действительно описано: The isolation level can be overridden, if necessary, for individual SELECT statements by specifying a table-level locking hint. Specifying a table-level locking hint does not affect other statements in the session. It is recommended that table-level locking hints be used to change the default locking behavior only when absolutely necessary. И мной ожидалось, что если из двух сессий будет выполнено SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, то при вставке новой информации (ID) из обеих сессий, та которая начала транзакцию первее заблокирует часть таблицы по индексу, а вторая будет ОЖИДАТЬ завершения транзакции в первой. И если например в третьей сессии попытались изменить существующие данные, то эта третья сессия не будет ожидать первых двух. А на практике SQL Server срубает вторую и третью сессии и говорит, что они вызывают DEADLOCK ! >Вывод получается такой: НАДО ПРИДУМЫВАТЬ СПЕЦИФИЧЕСКИЕ АЛГОРИТМЫ ДЛЯ РАСЧЕТА [ID] >Зачем интересно? Мне пришлось использовать подход описанный в статье только раз, да и то только из за специфичности >задачи. А Вам зачем? >И вот мы подошли к сути вопроса: КАК НЕ ПОЛЬЗУЯСЬ WITH (TABLOCKX) КОРРЕКТНО ЗАБЛОКИРОВАТЬ ЧАСТЬ ТАБЛИЦЫ, >Опять вопрос - зачем? В чем смысл этой блокировки, что она Вам дает? У меня порядка 100 одновременно активных сессий, в которых юзера вводят и корректируют информацию, обращаясь к одним и тем же таблицам. И мне надо сделать так, что бы юзера не сидели по часу в ожидании реакции системы на вставку новой или изменение существующей информации (если тупо пользоваться хинтами типа TABLOCKX) >Ключевой Ваш вопрос - ЗАЧЕМ ЭТО ВООБЩЕ НУЖНО И ГДЕ ПРАКТИЧЕСКИ ПРИМЕНЯЕТСЯ ??? >Бывает, что нужно использовать эти установки, но такая необходимость возникает крайне редко, во всяком случае я даже >с ходу и пример придумать не могу. Я имел в виду, что если это все работает не так как мной ожидалось, то как практически (ПРАВИЛЬНО) это использовать для перечисленных мной выше реальных задач ------------------------ 2 ALL Не смотря на столь долгое обсуждение сабжа я к сожалению так и не получил ясного ответа. Неужели никто не может толково сказать как все таки надо поступить (можно с конкретным примерчиком SQL скрипта) в моем случае, ведь эта проблема возникает практически у каждого программера, разрабатывающего клиент-серверные системы, расчитанные на одновременную работу многих пользователей. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.07.2001, 20:47 |
|
||
|
Чем принципиально отличается ...
|
|||
|---|---|---|---|
|
#18+
>Не смотря на столь долгое обсуждение сабжа я к сожалению так и не получил ясного ответа. Хм... я например так и не увидел ясного вопроса В чем собсно проблема? В SQL сервере есть дастаточно четкая система блокировок, вмешиваться в эту систему нужно только в крайних случаях, четко понимая при этом зачем это Вам нужно, иначе получите А на практике SQL Server срубает вторую и третью сессии и говорит, что они вызывают DEADLOCK ! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2001, 05:15 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=32009739&tid=1826158]: |
0ms |
get settings: |
10ms |
get forum list: |
17ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
29ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
59ms |
get tp. blocked users: |
2ms |
| others: | 256ms |
| total: | 391ms |

| 0 / 0 |
