Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
Топик располагается на нескольких страницах: [1] 2 3 вперед Ctrl→ все |
JohnySC Member Откуда: Сообщений: 33 |
Здравствуйте! Прошу помощи в решении серьезной проблемы при работе 1С ЗБУ 8. В ИБ расчитывается зарплата сотрудникам где-то 50-ти небольшим организациям (школы, садики), работает ИБ нормально, но при начислении зарплаты в конце месяца возникают сильные тормоза, и много расчетчиков вылетают во взаимоблокировки, причем каждый расчетчик считает свою организацию, т.е. данные непересекающиеся, по идее взаимоблокировок быть не должно. Что-то подобное обсуждалось тут. Но я не могу во всех деталях разобраться сам - знаний не хватает, да и у меня все-таки другая ситуация. Что сделано: 1) Пробовал помещать лог ИБ (файл LDF) на быстрый виртуальный диск в оперативной памяти - не помогает, ускоряется выполнение запросов, но взаимблокировки все-равно остаются. 2) Перенес ИБ на более мощный сервер с MS SQL 2012 - ничего не изменилось, то же только ускорение работы. 3) Пытался исследовать ситуацию с помощью 1С:ЦУП результаты есть, но мне не хватает знаний их правильно интерпретировать и сделать ответные действия. Вот одна из взаимоблокировок, в файлах приложил информацию из ЦУП. Куда дальше копать? Может что-то еще нужно исследовать? К сообщению приложен файл (ВЗ.zip - 11Kb) cкачать ![]() |
3 дек 12, 09:05 [13566518] Ответить | Цитировать Сообщить модератору |
invm Member Откуда: Москва Сообщений: 9633 |
Анализ взаимоблокировок в приложении SQL Server Profiler |
3 дек 12, 10:00 [13566734] Ответить | Цитировать Сообщить модератору |
ambarka_max Member Откуда: Россия Сообщений: 517 |
У Вас там удаление идет из _CRgActP579 через кучу джойнов по крайней мере по 3-м полям (запрос, кстати, тот еще баклажан). Предполагаю в этом засада, т.к. логично будет лочиться вся таблица. Если запрос на удаление формируется самой платформой, то это попадос. А если запрос на удаление в конфигурации формируется - то нужно переписать его сбором _CRgActP579.PK во времянку и дальнейшее удаление через джойн на эту времянку. По моему как то так. |
3 дек 12, 10:05 [13566758] Ответить | Цитировать Сообщить модератору |
JohnySC Member Откуда: Сообщений: 33 |
Ну тут если я правильно понимаю я получу граф блокировки - так он и так есть в ЦУПе, я его тоже вложил в прикрепленный файл, или я не все понимаю? |
||
3 дек 12, 10:53 [13567043] Ответить | Цитировать Сообщить модератору |
JohnySC Member Откуда: Сообщений: 33 |
Ну тут как я понял взаимоблокировка происходит при параллельной записи двумя пользователями регистра: У одного : ОбщийМодуль.ПроведениеРасчетовПереопределяемый.Модуль : 4831 : НаборЗаписейРегистра.Записать(Истина, ТолькоЗапись, Истина, Ложь); У второго: Документ.НачислениеЗарплатыРаботникамОрганизаций.МодульОбъекта : 1299 : НаборОсновныеНачисления.Записать(Истина, Ложь, Истина, Ложь); Оба действия - системные процедуры, которые платформа выполняет сама. И как я понял оба действия приводят к одинаковому запросу у SQL: DELETE FROM T2 FROM #tt266 T1 WITH(NOLOCK) INNER JOIN _CRgActP579 T2 ON T2._RecorderTRef = T1._RecorderTRef AND T2._RecorderRRef = T1._RecorderRRef AND T2._LineNo = T1._LineNo WHERE (T2._RecorderTRef = T1._RecorderTRef AND T2._RecorderRRef = T1._RecorderRRef AND T2._LineNo = T1._LineNo) AND CASE WHEN T2._RecorderTRef = T1._RecorderTRef AND T2._RecorderRRef = T1._RecorderRRef AND T2._LineNo = T1._LineNo THEN CASE WHEN (EXISTS(SELECT 1 FROM _CRg542 T3 INNER JOIN (SELECT 1 AS SDBL_DUMMY) SDBL_DUAL ON T2._RecorderTRef = T3._RecorderTRef AND T2._RecorderRRef = T3._RecorderRRef AND T2._LineNo = T3._LineNo LEFT OUTER JOIN (SELECT DISTINCT ? AS SDBL_RLS_SIGNAL_, T5._Reference39_IDRRef AS Q_001_F_000RRef FROM _Reference39_VT772 T5 WHERE (T5._Fld774RRef = ?)) T4 ON 1=1 LEFT OUTER JOIN _Reference74 T6 ON (((T6._Fld1103RRef = T3._Fld545RRef) AND (NOT (((T6._Fld1103RRef = ?))))) OR (T6._IDRRef = T3._Fld545RRef)) WHERE (NOT ((EXISTS(SELECT ? AS Q_002_F_000_ FROM _InfoRg5904 T7 WHERE (T7._Fld5905RRef = T4.Q_001_F_000RRef) AND (CASE WHEN (T7._Fld5906RRef = 0xB78E164A78CB03FE417290B1004B3CEF) THEN CASE WHEN EXISTS(SELECT 1.0 AS Q_004_F_000_ FROM (SELECT 0x01 AS SDBL_RLS_SIGNAL_, 1.0 AS Q_003_F_000_) T8 INNER JOIN _InfoRg5951 T9 ON ((((T9._Fld5952_TYPE = CASE WHEN T6._IDRRef IS NOT NULL THEN 0x08 END AND T9._Fld5952_RTRef = CASE WHEN T6._IDRRef IS NOT NULL THEN 0x0000004A END AND T9._Fld5952_RRRef = T6._IDRRef) AND (T9._Fld5953RRef = 0xB78E164A78CB03FE417290B1004B3CEF)) AND ((T9._Fld5954RRef = T7._Fld5905RRef) OR (T9._Fld5954RRef = 0xA598BA7EF1CB9366471C098758D5710E))) AND (T9._Fld5956 = 0x01)) WHERE 1=1) THEN 0x01 ELSE 0x00 END ELSE 0x01 END = ?))))) AND (NOT ((T4.Q_001_F_000RRef IS NULL)))) OR EXISTS(SELECT 1 FROM _CRg542 T10 INNER JOIN (SELECT 1 AS SDBL_DUMMY) SDBL_DUAL ON T2._RecorderTRef = T10._RecorderTRef AND T2._RecorderRRef = T10._RecorderRRef AND T2._LineNo = T10._LineNo WHERE 1=0)) THEN 0 ELSE 2000000000 END + 2000000000 ELSE 0 END = 2000000000 Как-же тут можно помочь платформе? |
||
3 дек 12, 11:06 [13567119] Ответить | Цитировать Сообщить модератору |
aleks2
Guest |
1. Ежели бы лочилась таблица - взаимоблокировок бы не было. 2. Поэтому самый дешевый способ, если расчет быстрый, принудительно блокировать все, участвующие в нем таблицы. ЗЫ. Более сложный способ - обеспечение кластерного индекса в таблицах "по организациям". Но это не панацея. Да и, наскока я припоминаю по 1C7.7, вмешаться в структуру таблиц 1C затруднительно. |
||
3 дек 12, 11:07 [13567130] Ответить | Цитировать Сообщить модератору |
aleks2
Guest |
Это нада отлить в бронзу. |
||
3 дек 12, 11:10 [13567143] Ответить | Цитировать Сообщить модератору |
JohnySC Member Откуда: Сообщений: 33 |
|
||||||
3 дек 12, 11:36 [13567310] Ответить | Цитировать Сообщить модератору |
alexeyvg Member Откуда: Moscow Сообщений: 31778 |
Но для локальной временной таблицы этот хинт не нужен, блокировки всё равно не будет, поэтому выглядит странно. |
||||
3 дек 12, 12:02 [13567543] Ответить | Цитировать Сообщить модератору |
JohnySC Member Откуда: Сообщений: 33 |
Вот запрос с именами объектов 1С: DELETE FROM T2 FROM #tt164 T1 WITH(NOLOCK) INNER JOIN РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия T2 ON РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._RecorderTRef = T1._RecorderTRef AND РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._RecorderRRef = T1._RecorderRRef AND РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._LineNo = T1._LineNo WHERE (РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._RecorderTRef = T1._RecorderTRef AND РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._RecorderRRef = T1._RecorderRRef AND РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._LineNo = T1._LineNo) AND CASE WHEN РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._RecorderTRef = T1._RecorderTRef AND РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._RecorderRRef = T1._RecorderRRef AND РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._LineNo = T1._LineNo THEN CASE WHEN (EXISTS(SELECT 1 FROM РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций T3 INNER JOIN (SELECT 1 AS SDBL_DUMMY) SDBL_DUAL ON РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._RecorderTRef = РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций_T3.Регистратор AND РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._RecorderRRef = РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций_T3.Регистратор AND РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._LineNo = РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций_T3.НомерСтроки LEFT OUTER JOIN (SELECT DISTINCT ? AS SDBL_RLS_SIGNAL_, Справочник.ГруппыПользователей.ПользователиГруппы_T5._Reference39_IDRRef AS Q_001_F_000RRef FROM Справочник.ГруппыПользователей.ПользователиГруппы T5 WHERE (Справочник.ГруппыПользователей.ПользователиГруппы_T5.Пользователь = ?)) T4 ON 1=1 LEFT OUTER JOIN Справочник.Организации T6 ON (((Справочник.Организации_T6.ГоловнаяОрганизация = РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций_T3.Организация) AND (NOT (((Справочник.Организации_T6.ГоловнаяОрганизация = ?))))) OR (Справочник.Организации_T6.Ссылка = РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций_T3.Организация)) WHERE (NOT ((EXISTS(SELECT ? AS Q_002_F_000_ FROM РегистрСведений.НазначениеВидовОбъектовДоступа T7 WHERE (РегистрСведений.НазначениеВидовОбъектовДоступа_T7.ГруппаПользователей = T4.Q_001_F_000RRef) AND (CASE WHEN (РегистрСведений.НазначениеВидовОбъектовДоступа_T7.ВидОбъектаДоступа = 0xB78E164A78CB03FE417290B1004B3CEF) THEN CASE WHEN EXISTS(SELECT 1.0 AS Q_004_F_000_ FROM (SELECT 0x01 AS SDBL_RLS_SIGNAL_, 1.0 AS Q_003_F_000_) T8 INNER JOIN РегистрСведений.НастройкиПравДоступаПользователей T9 ON ((((РегистрСведений.НастройкиПравДоступаПользователей_T9.ОбъектДоступа = CASE WHEN Справочник.Организации_T6.Ссылка IS NOT NULL THEN 0x08 END AND РегистрСведений.НастройкиПравДоступаПользователей_T9.ОбъектДоступа = CASE WHEN Справочник.Организации_T6.Ссылка IS NOT NULL THEN 0x0000004A END AND РегистрСведений.НастройкиПравДоступаПользователей_T9.ОбъектДоступа = Справочник.Организации_T6.Ссылка) AND (РегистрСведений.НастройкиПравДоступаПользователей_T9.ВидОбъектаДоступа = 0xB78E164A78CB03FE417290B1004B3CEF)) AND ((РегистрСведений.НастройкиПравДоступаПользователей_T9.Пользователь = РегистрСведений.НазначениеВидовОбъектовДоступа_T7.ГруппаПользователей) OR (РегистрСведений.НастройкиПравДоступаПользователей_T9.Пользователь = 0xA598BA7EF1CB9366471C098758D5710E))) AND (РегистрСведений.НастройкиПравДоступаПользователей_T9.Запись = 0x01)) WHERE 1=1) THEN 0x01 ELSE 0x00 END ELSE 0x01 END = ?))))) AND (NOT ((T4.Q_001_F_000RRef IS NULL)))) OR EXISTS(SELECT 1 FROM РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций T10 INNER JOIN (SELECT 1 AS SDBL_DUMMY) SDBL_DUAL ON РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._RecorderTRef = РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций_T10.Регистратор AND РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._RecorderRRef = РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций_T10.Регистратор AND РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций.ПериодыДействия_T2._LineNo = РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций_T10.НомерСтроки WHERE 1=0)) THEN 0 ELSE 2000000000 END + 2000000000 ELSE 0 END = 2000000000А как-то можно отловить что передается в таблицу #tt164 ? Или это и не надо? |
||
3 дек 12, 12:19 [13567660] Ответить | Цитировать Сообщить модератору |
aleks2
Guest |
Имею вопрос: если эти ваши 50 организаций ничем не связаны - нахера вы их запихали в одну базу? |
3 дек 12, 12:36 [13567765] Ответить | Цитировать Сообщить модератору |
JohnySC Member Откуда: Сообщений: 33 |
Кто-нибудь может пояснить что значит вопрос в "SELECT DISTINCT ? AS SDBL_RLS_SIGNAL_" тут каким-то объектам ЦУП не смог чтоли имя определить? И еще странная конструкция "WHERE 1=0" она наверно образовалась из чего-то в коде? |
3 дек 12, 12:39 [13567803] Ответить | Цитировать Сообщить модератору |
JohnySC Member Откуда: Сообщений: 33 |
|
||
3 дек 12, 12:45 [13567850] Ответить | Цитировать Сообщить модератору |
Программист 1с Member Откуда: Москва Сообщений: 9287 |
Бюджетку не знаю. Но при расчете - да блокируется. Там помнится расчет, запись, расчет на основе записи и еще одна запись... Как вариант - регламентным заданием вечером пусть расчитывает по порядку. Либо разделите по времени расчеты каждого учетчика. |
||||
3 дек 12, 13:32 [13567984] Ответить | Цитировать Сообщить модератору |
dalex1973 Member Откуда: Польша Сообщений: 287 |
Программисты чтоб не маятся добавлением/убиранием части запроса, сделали код типа string Query = ".. WHERE 1=@Parameter" Также много "странного" кода появилось при приведении кода к ANSI-стандарту (для совместимости с другими RDMS). Например, замена CROSS JOIN на LEFT OUTER JOIN ON 1=1 . Поэтому: |
||
3 дек 12, 13:45 [13568091] Ответить | Цитировать Сообщить модератору |
alexeyvg Member Откуда: Moscow Сообщений: 31778 |
|
||||
3 дек 12, 14:12 [13568361] Ответить | Цитировать Сообщить модератору |
JohnySC Member Откуда: Сообщений: 33 |
Они видимо копированием создают новый документ, очищают его, заполняют автоматически, делают полный расчет, и проводят. И им надо видеть результат расчета и проведения, регламентным не получится... |
||
3 дек 12, 14:47 [13568730] Ответить | Цитировать Сообщить модератору |
JohnySC Member Откуда: Сообщений: 33 |
Сейчас пробую на копии повторить ситуацию, чтобы уже расчетчиков не гонять, а самому тестировать. Хочу написать обработку, которая будет по определенной организации рассчитывать зарплату за пару месяцев, и запускать ее в нескольких сеансах одновременно. Надеюсь получить взаимоблокировки. |
4 дек 12, 06:00 [13572359] Ответить | Цитировать Сообщить модератору |
МуМу Member Откуда: Сообщений: 1134 |
У нас есть продукт тесно интегрированный с 1С,MSSQL. Посмотрите http://www.softpoint.ru/perfexpert.php http://www.softpoint.ru/products_id3.htm Смысл в том что он не нагружает систему(не более 3 %) при этом позволяет непрерывно мониторить производительность. |
4 дек 12, 08:16 [13572495] Ответить | Цитировать Сообщить модератору |
МуМу Member Откуда: Сообщений: 1134 |
Учтите что в некоторых случаях 1С блокирует на уровне платформы самостоятельно. На память не помню , но в некоторых релизах было что более 20000 записей изменений по регистру приводило к автоматической блокировке всего регистра на уровне сервера приложений.(приблизительно так) |
4 дек 12, 08:26 [13572519] Ответить | Цитировать Сообщить модератору |
JohnySC Member Откуда: Сообщений: 33 |
Рад за Вас, но мы садики и школы из России... |
||
6 дек 12, 09:06 [13585538] Ответить | Цитировать Сообщить модератору |
МуМу Member Откуда: Сообщений: 1134 |
Ммм, а я думал холдинг из 50-и трубопрокатных заводиков:) А если серьезно, первое что вы должны сделать - смоделировать ситуацию. Смоделируйте на двух организациях пересечение по блокировкам после этого проще будет и в 1С в отладке понять точнее строки кода и в MSSQL по трассам понять проблемы. |
6 дек 12, 10:40 [13585986] Ответить | Цитировать Сообщить модератору |
JohnySC Member Откуда: Сообщений: 33 |
Смоделировал! Написал обработку, получил взаимоблокировки. Прикладываю файл с трассировкой. По советам в интернете, надо разобраться хотя бы с самой простой взаимоблокировкой, по текущей трассировке получается самая простая ситуация, это когда взаимно блокируются два простеньких запроса на удаление:DELETE FROM T2 FROM #tt59 T1 WITH(NOLOCK) INNER JOIN _CRgActP579 T2 ON T2._RecorderTRef = T1._RecorderTRef AND T2._RecorderRRef = T1._RecorderRRef AND T2._LineNo = T1._LineNo WHERE T2._RecorderTRef = T1._RecorderTRef AND T2._RecorderRRef = T1._RecorderRRef AND T2._LineNo = T1._LineNoи DELETE FROM T2 FROM #tt73 T1 WITH(NOLOCK) INNER JOIN _CRgActP579 T2 ON T2._RecorderTRef = T1._RecorderTRef AND T2._RecorderRRef = T1._RecorderRRef AND T2._LineNo = T1._LineNo WHERE T2._RecorderTRef = T1._RecorderTRef AND T2._RecorderRRef = T1._RecorderRRef AND T2._LineNo = T1._LineNo У одного режим блокировки переходит из IX в U, у второго остается U ![]() Кто подскажет что с этим мне делать? Куда копать-то? К сообщению приложен файл (ТрассировкаSQL.zip - 4Kb) cкачать ![]() |
6 дек 12, 12:50 [13587412] Ответить | Цитировать Сообщить модератору |
invm Member Откуда: Москва Сообщений: 9633 |
JohnySC, У вас все ровно то же самое, что и автора темы, ссылку на которую вы привели в своем первом посте. Там же есть и способ борьбы. |
6 дек 12, 13:07 [13587603] Ответить | Цитировать Сообщить модератору |
JohnySC Member Откуда: Сообщений: 33 |
Спасибо, за подтверждение, invm. Перечитал еще раз ту тему, почитал про триггеры стало более-менее понятно о чем в ней речь. Завтра буду пробовать. Как я понял мне нужен такой триггер:Create trigger [dbo].[on_delete_CRgActP579] on [dbo].[_CRgActP579] instead of delete as begin Delete from T1 From deleted as T3 left join _CRgActP579 as T2 on T2._RecorderTRef=T3._RecorderTRef AND T2._RecorderRRef=T3._RecorderRRef AND T2._LineNo=T3._LineNo end;Поправьте плиз, если что не так! Только я не совсем понимаю, что будет если 1С каким-то другим образом будет удалять данные из этой таблицы (например с on на 2 условия, а не на 3) все равно сработает этот триггер и возникнет непредвиденное поведение? |
6 дек 12, 16:34 [13589277] Ответить | Цитировать Сообщить модератору |
Топик располагается на нескольких страницах: [1] 2 3 вперед Ctrl→ все |
Все форумы / Microsoft SQL Server | ![]() |