| 
			
			 | 
		#1 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
			
			
			Пакетные задания - batchConstraint (AX 2012 R2)
			 
			
			Тут недавно произошло неприятное событие - некорректно прошел пересчет склада. При разноске ГК система взяла не все сопоставления. Соответственно, ваучер сопоставления неполный и не во всех сопоставлениях (с заполненными счетами) проставлен признак Posted. Расследование показало, что задача Завершение уровня расчета стартанула еще до завершения связанных подзадач (из BatchConstraint), быстро завершилась и создала задачу разноски в ГК, а задачи по генерации сопоставлений продолжили выполняться и нагенерили необработанных сопоставлений. 
		
		
		
		
		
		
		
	Есть подозрение, что некорректно работает подсистема пакетных заданий, а именно метод BatchRun::serverProcessDependencies. В этом методе у МС зачем то ставятся принудительно хинты readCommittedLock. Я вот грешным делом думал, что read commited и так используется в аксапте всегда, если точнее read commited snapshot. Но то ли МС об этом не знает, то ли этот метод особенный. Если метод особенный, то меня смущает, что для таблицы Batch в методе нету хинта: X++: batchJob.readCommittedLock(true); constraintsOr.readCommittedLock(true); batchDependsOr.readCommittedLock(true); constraintsAnd.readCommittedLock(true); batchDependsAnd.readCommittedLock(true); Кто что думает по этому поводу? Либо можно все списать на барабашку.  | 
| 
	
 | 
| 
			
			 | 
		#2 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			А может быть проводки по сопоставлению вам создал пересчет себестоимости, который может запускаться автоматом после закрытия склада? Просто у них ваучеры совпали. (Номерные серии разные, по идее такое возможно при определенных настройках). Правда даты в Inventsettlement должны быть разными тогда. Вы их сравнивали ?
		 
		
		
		
		
		
		
		
	 | 
| 
	
 | 
| 
			
			 | 
		#3 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
		
			Сообщение от Logger
			 
 
			А может быть проводки по сопоставлению вам создал  пересчет себестоимости, который может запускаться автоматом после  закрытия склада? Просто у них ваучеры совпали. (Номерные серии разные,  по идее такое возможно при определенных настройках). Правда даты в  Inventsettlement должны быть разными тогда. Вы их сравнивали ? 
		
	Вообще в ваучер попал только первый InventSettlement. По времени формирование ваучера и формирование сопоставлений стартанули в одну секунду. И разноска в ГК естественно завершилась сильно раньше формирования InventSettlement. Последний раз редактировалось Masel; 03.08.2017 в 09:38.  | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: Logger (1). | |
| 
			
			 | 
		#4 | 
| 
			
			 Moderator 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Я такое видел в DAX2009. Причем проблемы обработки constraints, почему-то случались только в случае Runtime Batch Job. В какой-то из своих доработок, я просто заменил RuntimeJob на стандартный. В общем - это не барабашка, это действительно иногда случается. Однако же закономерностей я не нашел...
		 
		
		
		
		
		
		
		
	 | 
| 
	
 | 
| 
			
			 | 
		#5 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Было такое, расследование показало, что MS SQL некорректно выполняет сформированные в данном методе запросы с exists/notexists join когда они выполняются одновременно с другими запросами на обновление Batch. Времени на детальный разбор не предвиделось и была сделана затычка в виде блокировочной таблички, которая не дает обновлять Batch в классе BatchRun одновременно с нескольких AOSов.
		 
		
		
		
		
		
		
		
	 | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: Logger (3). | |
| 
			
			 | 
		#6 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
На первый взгляд, примерно такую защиту предоставляет табличка batchGlobal и код по ее блокировке в методах BatchRun::ServerGet* BatchRun::ServerProcess* Вы не пробовали просто ее задействовать ? Хотя возможно я ошибаюсь - глубоко не вникал.  | 
| 
	
 | 
| 
			
			 | 
		#7 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
PS. Изменение уровня изоляции транзакций не улучшает ситуацию. PS2. Затыкания только в serverProcessDependencies недостаточно, надо лопатить во всех методах на изменение Batch.  | 
| 
	
 | 
| 
			
			 | 
		#8 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Откопал из загашников запросик, кажется это тот, на котором я ловил ошибочное поведение MS SQL : 
		
		
		
		
		
		
		
	X++: BEGIN TRAN UPDATE BATCH SET STATUS=5 WHERE ((STATUS=1) AND (CONSTRAINTTYPE=0)) AND EXISTS ( SELECT 'x' FROM BATCHJOB T2 WITH ( READCOMMITTEDLOCK) WHERE ((T2.STATUS=2) AND (BATCH.BATCHJOBID=T2.RECID)) AND NOT (EXISTS ( SELECT 'x' FROM BATCHCONSTRAINTS T3 WITH ( READCOMMITTEDLOCK) WHERE EXISTS ( SELECT 'x' FROM BATCH T4 WITH ( READCOMMITTEDLOCK) WHERE (((T3.DEPENDSONBATCHID=T4.RECID) AND (T3.BATCHID=BATCH.RECID)) AND ((((T4.STATUS<>3) AND (T4.STATUS<>4)) OR ((T3.EXPECTEDSTATUS=4) AND (T4.STATUS=3))) OR ((T3.EXPECTEDSTATUS=4) AND (T4.STATUS=3)))))))) --COMMIT TRAN --ROLLBACK TRAN 1. Создать тестовую среду 2. Открыть и запустить запросик в одном окне SSMS без завершения транзакции 3. Открыть и запустить запросик во втором окне SSMS без завершения транзакции 4. Завершить транзакции в первом и затем во втором окне (или наоборот) 5. Насладится результатами  | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: Logger (5), Raven Melancholic (10). | |
| 
			
			 | 
		#9 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			А какая была версия SQL Server?
		 
		
		
		
		
		
		
		
	 | 
| 
	
 | 
| 
			
			 | 
		#10 | 
| 
			
			 Участник 
		
			
	 | 
	
	|
| 
	
 | 
| 
			
			 | 
		#11 | 
| 
			
			 NavAx 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Поспрашайте в MS свежие хотфиксы. Мы им багов по поводу batchJobs в R2 насыпали изрядно и они почти все пофиксили.
		 
		
		
		
		
		
		
			
				__________________ 
		
		
		
		
	Isn't it nice when things just work?  | 
| 
	
 | 
| 
			
			 | 
		#12 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Для истории: есть KB 3216955 KB 3216955, Bug Id 3804879 "Continuous dead locks in batch" для AX 2012 R2, где реализован целый ряд исправлений в классе BatchRun. Они сводятся к тому, чтобы при обновлении таблиц пакетной инфраструктуры вместо оптимистичной конкуренции использовать mutex на уровне СУБД, управляемый с помощью класса ReqReaderWriterLock. Такой подход позволяет надежно синхронизировать различные потоки пакетных обработчиков, в том числе выполняющиеся на разных пакетных серверах. См. также соотв. изменения в коде.
		 
		
		
		
		
		
		
		
	 | 
| 
	
 | 
| 
			
			 | 
		#13 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
			
			 
			
			2012 R3. Внесены все изменения по мьютексам в BatchRun и даже больше (ускоряющие хинты), но неожиданно всплыла очень медленная вставка в таблицу BatchConstraintsHistory. Из-за этого другие пакетники нарываются на блокировку мьютекса и ничего не стартует и не двигается десятками минут. Переиндексации и обновление статистик тут особо не работают, так как таблички часто меняются, а структура запроса не позволяла применить стандартные мантры хинтов из 2012 (forceSelectOrder forceNestedLoop). Но удалось переписать и этот запрос. Может кому-то пригодится. 
		
		
		
		
		
		
		
	BatchRun.serverProcessFinishedJobs Оригинальный код: X++: insert_recordset batchConstraintsHistory (BatchId, ExpectedStatus, DependsOnBatchId) select RecId from batchHistory join ExpectedStatus from batchConstraints where batchHistory.BatchId == batchConstraints.BatchId join RecId from batchHistoryDepends where batchHistoryDepends.BatchId == batchConstraints.DependsOnBatchId exists join batchJobHistory where batchJobHistory.Finishing == 1 && batchJobHistory.RecId == batchHistory.BatchJobHistoryId && batchJobHistory.RecId == batchHistoryDepends.BatchJobHistoryId; X++: insert_recordset batchConstraintsHistory (DependsOnBatchId, ExpectedStatus, BatchId) select forcePlaceholders forceSelectOrder forceNestedLoop batchJobHistory where batchJobHistory.Finishing == 1 join RecId from batchHistoryDepends where batchHistoryDepends.BatchJobHistoryId == batchJobHistory.RecId join ExpectedStatus from batchConstraints where batchConstraints.DependsOnBatchId == batchHistoryDepends.BatchId join RecId from batchHistory where batchHistory.BatchJobHistoryId == batchJobHistory.RecId && batchHistory.BatchId == batchConstraints.BatchId;  | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: Logger (3), A_BAS (2). | |
| 
			
			 | 
		#14 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
		
			Сообщение от gl00mie
			 
 
			Для истории: есть KB 3216955 KB 3216955, Bug Id 3804879 "Continuous dead locks in batch" для AX 2012 R2, где реализован целый ряд исправлений в классе BatchRun. Они сводятся к тому, чтобы при обновлении таблиц пакетной инфраструктуры вместо оптимистичной конкуренции использовать mutex на уровне СУБД, управляемый с помощью класса ReqReaderWriterLock. Такой подход позволяет надежно синхронизировать различные потоки пакетных обработчиков, в том числе выполняющиеся на разных пакетных серверах. См. также соотв. изменения в коде. 
		
	Просто установить недостаточно, необходимо еще включить, вставив запись в sysGlobalConfig Мы пробовали сделать на одном из клиентов(у них очень много пакетных заданий), в итоге это работало где-то день, потом все зависло. Т.е. какая-то сессия взяла этот мутекс и при этом ничего не делала. Попробовали еще раз, такая же история через день. В итоге решили что постоянные деадлоки это меньшее зло, чем полностью зависающая система Вопрос - кто нибудь побеждал эти деадлоки(они встречаются практически на всех клиентах, где несколько пакетных АОСов) и если да, то как? X++: #define.ConfigName_EnableBatchRunServerTaskLock('EnableBatchRunServerTaskLock') select Value from sysGlobalConfig where sysGlobalConfig.Name == #ConfigName_EnableBatchRunServerTaskLock;  | 
| 
	
 | 
| 
			
			 | 
		#15 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			У меня используются эти мьютексы. Но я точечно изменения из CU13 перенес. Там все прозрачно и не проверяется ничего из sysGlobalConfig. Подвисания были как раз из-за batchConstraintsHistory, но моя правка свежая и утверждать, что проблема ушла окончательно еще не могу.
		 
		
		
		
		
		
		
		
	 | 
| 
	
 | 
| 
			
			 | 
		#16 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			В стандарте это точно надо включать. А можете запустить sp_BlitzLock для базы? она покажет как раз все деадлоки с момента последнего рестарта сервера, интерестно, будут ли там таблицы с Batch..
		 
		
		
		
		
		
		
		
	 | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: AlGol (3), Logger (1). | |
| 
			
			 | 
		#17 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
X++: (@P1 int,@P2 datetime2,@P3 datetime2,@P4 int,@P5 int,@P6 int,@P7 int) UPDATE BATCH SET STATUS=@P1,ENDDATETIME=@P2,MODIFIEDDATETIME=@P3,RECVERSION=@P4,ENDDATETIMETZID=@P5 WHERE (STATUS=@P6) AND NOT (EXISTS (SELECT 'x' FROM SYSCLIENTSESSIONS T2 WITH ( READCOMMITTEDLOCK) WHERE (((BATCH.SESSIONIDX=T2.SESSIONID) AND (BATCH.SESSIONLOGINDATETIME=T2.LOGINDATETIME)) AND (T2.STATUS!=@P7)))) X++: (@P1 int,@P2 datetime2,@P3 int,@P4 datetime2,@P5 bigint,@P6 int) UPDATE BATCH SET STATUS=@P1,ENDDATETIME=@P2,RECVERSION=@P3,MODIFIEDDATETIME=@P4 WHERE ((RECID=@P5) AND (RECVERSION=@P6)) Еще нашел дедлок по BATCHHISTORY. Но это тогда когда вставка еще долго могла выполнятся и пересечение с удалением из этой же таблицы. Удаления в BatchRun нет. Это удаление скорее всего из модуля WHS прилетело.  | 
| 
	
 | 
| 
			
			 | 
		#18 | 
| 
			
			 Участник 
		
			
	 | 
	
	|
| 
	
 | 
| 
			
			 | 
		#19 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Да, нашло много интересного. Да и SQL-сервер идет на рекорд 106 дней без перезагрузки. 
		
		
		
		
		
		
		
	Думаю что Batch проблема решается. Когда пакетных аосов много, то дедлоков тоже много. Проблемы глобальной как бы и нет, но когда смотришь на логи винды на аосах, то видишь сообщения о дедлоках. Раньше их было много. Теперь можно сказать, что нет совсем. Расположение кода с блокировкой мьютексов в стандарте вызывает вопросы. Почему они написаны после обновления GLOBAL-таблицы. Если бы стояли до, то меньше бы раз вызывались операции.  | 
| 
	
 | 
| Теги | 
| ax2012, batch, batchrun, reqreaderwriterlock, баг, блокировки, закрытие склада | 
| 
	
	 | 
	
		
  |