Регистрация  |  Вход

Locking in Salesforce

Товарищи поделитесь опытом.

На последнем проекте стал замечать очень странное поведение.

Начну с вводных данных:

есть такая общая задача - получить из базы "свободные" данные, тут же пометить как "занято для работы", отдать пользователю. Пользователь работает с данными, сохраняет и "освобождает" их. Естественно между получить данные, отметить как занято для работы должен работать 1 поток.

Но заметил, что ОЧЕНЬ часто нашим пользователям выдаются одни и те же данные. КАК? Оказывается что они как-то умудряются одновременно послать запрос и одновременно получить одни и те же данные из базы, отметить их как "занятые". Это конечно возможно с точки зрения теории вероятности послать одновременный запрос и попасть в один и тот же промежуток с миллисекунды. Но млин, не каждый же день!!!

Погуглил на эту тему и нашел модификатор SOQL запроса FOR UPDATE. Но это немного не то Данные то все равно могут получить "одновременно" но изменить сможет кто-то один (тот кто первый получил). Другой получит Exception.

А как можно в Salesforce организовать очередь? В других языках программирования это очень популярная тема "Concurrency", есть ли что-то похожее в Salesforce? Вот надо мне чтобы в метод выполнялся гарантированно только в одном потоке, а остальные ждали своей очереди.

Может есть какие костыли на эту тему?

Товарищи поделитесь опытом.
На последнем проекте стал замечать очень странное поведение.
Начну с вводных данных:
есть такая общая задача -  получить из базы "свободные" данные, тут же пометить как "занято для работы",  отдать пользователю. Пользователь работает с данными, сохраняет и "освобождает" их. Естественно между получить данные, отметить как занято для работы должен работать 1 поток.
Но заметил, что ОЧЕНЬ часто нашим пользователям выдаются одни и те же данные. КАК? Оказывается что они как-то умудряются одновременно послать запрос и одновременно получить одни и те же данные из базы, отметить их как "занятые". Это конечно возможно с точки зрения теории вероятности послать одновременный запрос и попасть в один и тот же промежуток с миллисекунды. Но млин, не каждый же день!!!
Погуглил на эту тему и нашел модификатор SOQL запроса FOR UPDATE. Но это немного не то :( Данные то все равно могут получить "одновременно" но изменить сможет кто-то один (тот кто первый получил). Другой получит Exception.
А как можно в Salesforce организовать [b]очередь[/b]? В других языках программирования это очень популярная тема "Concurrency", есть ли что-то похожее в Salesforce? Вот надо мне чтобы в метод выполнялся гарантированно только в одном потоке, а остальные ждали своей очереди.
Может есть какие костыли на эту тему?
Есть очереди для Jobs - https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_queueing_jobs.htm

Это не то. Это не из области запрос-ответ. Нужно чтобы между запрос-ответ код выполнялся по очереди.
Но у меня такое предчувствие, что в Salesforce этого нет. Странно что никто до этого не сталкивался с такими проблемами.

Это не то. Это не из области запрос-ответ. Нужно чтобы между запрос-ответ код выполнялся по очереди.
Но у меня такое предчувствие, что в Salesforce этого нет. Странно что никто до этого не сталкивался с такими проблемами.

Вот думаю, а тема то очень интересная.
Вот придумал пример из жизни.
У меня есть объект в базе для которого я в триггере по сложному алгоритму проверяю на дубли в before_insert.
Получается что может возникнуть ситуация конкурентного выполнения 2х DML оепраций в одно и тоже время. Триггер проверил на дубли (дублей нет), но до момента записи в базу другой поток успевает создать запись-дубль. Но так как проверка уже прошла, то первая DML операция отрабатывает успешно. Получается что вроде проверка есть, но и дубли в базе тоже есть?
Или все-таки 2 DML операции не могут выполниться одновременно?

Вот думаю, а тема то очень интересная.
Вот придумал пример из жизни.
У меня есть объект в базе для которого я в триггере по сложному алгоритму проверяю на дубли в before_insert.
Получается что может возникнуть ситуация конкурентного выполнения 2х DML оепраций в одно и тоже время. Триггер проверил на дубли (дублей нет), но до момента записи в базу другой поток успевает создать запись-дубль. Но так как проверка уже прошла, то первая DML операция отрабатывает успешно. Получается что вроде проверка есть, но и дубли в базе тоже есть?
Или все-таки 2 DML операции не могут выполниться одновременно?

Не могут запись будет заблокирована.
Есть даже алгоритм для воспроизведенеия ошибки LOCKED.

Не могут запись будет заблокирована. 
Есть даже алгоритм для воспроизведенеия ошибки LOCKED.

Ну это уже хорошо. Осталось разобраться с конкурентным выполнением самого кода.

Ну это уже хорошо. Осталось разобраться с конкурентным выполнением самого кода.

Gres
Не могут запись будет заблокирована.
Есть даже алгоритм для воспроизведенеия ошибки LOCKED.

Абсолютно согласен, не могут. Происходит примерно так: первое вызов триггера делает SELECT ... FOR UPDATE, второй вызов триггера будет ждать в том же месте на том же SELECT ... FOR UPDATE и так будет продолжаться пока первый вызов триггера не закоммитит транзакцию (важен имменно конец транзакции, DML в коде триггера не разблокирует записи). Ну или будет Exception, потому что первый вызов триггера долго не может закоммитить.
Внимание, лочить везде надо в одинаковой последовательности, иначе может быть deadlock.

Конкурентное выполнение кода, тут наверное неважно, потому как общего у друх транзакций только данные из базы. Да и в Apex все равно нет примитивов синхронизации.

[quote="Gres"]Не могут запись будет заблокирована. 
Есть даже алгоритм для воспроизведенеия ошибки LOCKED.[/quote]

Абсолютно согласен, не могут. Происходит примерно так: первое вызов триггера делает SELECT ... FOR UPDATE, второй вызов триггера будет ждать в том же месте на том же SELECT ... FOR UPDATE и так будет продолжаться пока первый вызов триггера не закоммитит транзакцию (важен имменно конец транзакции, DML в коде триггера не разблокирует записи). Ну или будет Exception, потому что первый вызов  триггера долго не может закоммитить.
Внимание, лочить везде надо в одинаковой последовательности, иначе может быть deadlock.

Конкурентное выполнение кода, тут наверное неважно, потому как общего у друх транзакций только данные из базы. Да и в Apex все равно нет примитивов синхронизации. 

Как часто вы используете FOR UPDATE вручную в коде?

Как часто вы используете FOR UPDATE вручную в коде?

Dmitry Shnyrev
Как часто вы используете FOR UPDATE вручную в коде?

Пока только всего 1 раз приходилось

[quote="Dmitry Shnyrev"]Как часто вы используете FOR UPDATE вручную в коде?[/quote]
Пока только всего 1 раз приходилось