17.02.2023, 16:26 | #21 |
Участник
|
Попробуйте класс ReqReaderWriterLock
Можно проверить, заблокирована ли конкретная запись. Если не заблокирована, то заблокировать ее и обработать. Если заблокирована, то пропустить её и начать обрабатывать следующую запись. В качестве ключа в параметр _lockName метода tryEnterWriterLock передать уникальную строку, которая каким-то образом идентифицирует обрабатываемую запись. X++: ReqReaderWriterLock lockCleanup = ReqReaderWriterLock::construct(); while select myTable { if (lockCleanup.tryEnterWriterLock(int642str(myTable.RecId), 0)) // Блокируем, а если кем-то уже заблокировано, то обходим { ttsbegin; myTableUpd = MyTable::findRecId(myTable.RecId, true); //..................... myTableUpd.update(); ttscommit; } } lockCleanup.releaseAllLocks();
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/ Последний раз редактировалось Ace of Database; 17.02.2023 в 16:56. |
|
|
За это сообщение автора поблагодарили: sukhanchik (10). |
17.02.2023, 16:38 | #22 |
Участник
|
Такой подход еще хорош тем, что он блокирует только записи, обрабатываемые именно этим конкретным алгоритмом. Для этого в параметр в качестве ключа в параметр _lockName можно передавать не только RecId таблицы в текстовом виде, но и дописывать некий текстовый константный префикс, который определяет именно эту обработку.
__________________
Мои утилиты для Аксапты версий 3.0-2012: http://aceofdatabase.blogspot.com/ |
|
17.02.2023, 17:37 | #23 |
Участник
|
Подход может и хорош, но сам класс так себе. Недавно коллега обнаружил что блокировка ставится без учета имени бд ! Т.е. если у вас на одном инстансе SQL крутится 2 инсталляции аксапты (2 рабочие) или дев и тест, то между ними могут быть блокировки из-за того что этот класс не учитывает имя бд !
В частности это выражается в неожиданных блокировках при попытке одновременно запустить синхронизацию в двух инсталляциях аксапты. Также при пакетной обработке и куче других мест где задействован этот класс. Попробовал его исправить, добавив имя базы в имени блокировки. |
|
|
За это сообщение автора поблагодарили: sukhanchik (10), Ace of Database (10), trud (2), gl00mie (10), SRF (5). |
17.02.2023, 17:38 | #24 |
Участник
|
А вообще, я бы не изобретал разные костыли и по максимуму бы задействовал БД через индексы (как выше предлагал). Так проще и надежнее. И весь контроль на уровне БД идет.
|
|
22.02.2023, 17:01 | #25 |
Участник
|
Из Аксапты фильтрованный индекс не сделать, она такое не умеет, но из Аксапты можно сделать "обычный" уникальный индекс, а уже на уровне СУБД сделать его фильтрованным. Замечено, что синхронизация БД из Аксапты "не различает", фильтрованный в базе индекс или нет, а смотрит только на название/порядок полей и проч. Таким вот образом в D365FO решалась задача "отключения" ненужных/вредных индексов стандартного приложения: поменять свойства стандартного индекса в приложении нельзя (с тех пор, как закрыли overlayering), но можно на стороне СУБД добавить индексу условие вида where partition = 0 - и вуаля! А тут можно добавить условие вида where active = 1. Конечно, если вдруг понадобится поменять индекс, то синхронизация попытается его пересоздать, и тогда надо будет заново приклеивать фильтрацию со стороны СУБД. Но в остальном всё работает нормально.
Последний раз редактировалось gl00mie; 22.02.2023 в 17:04. |
|
|
За это сообщение автора поблагодарили: Logger (5). |