У меня есть процесс, который вызывается из нескольких потоков, который выполняет следующее:
- Начать транзакцию
- Выберите единицу работы из рабочего стола, найдя следующую строку, где
IsProcessed=0
с подсказками (UPDLOCK, HOLDLOCK, READPAST)
- Обработка единицы работы (хранимые процедуры на C # и SQL)
- Совершить транзакцию
Идея этого состоит в том, что поток погружается в пул для «следующего» фрагмента работы и обрабатывает его, а блокировки существуют для того, чтобы один фрагмент работы не обрабатывался дважды. (порядок не имеет значения).
Все это прекрасно работало в течение нескольких месяцев. До сегодняшнего дня, когда я осознал, что, несмотря на включение изоляции моментальных снимков и установление по умолчанию на уровне базы данных, фактический код создания транзакции вручную устанавливал уровень изоляции «ReadCommitted».
Я должным образом изменил это на «Снимок», и, конечно же, сразу же получил следующее сообщение:
Вы можете указать блокировку READPAST только в READ COMMITTED или REPEATABLE READ
Основная причина блокировки строки состояла в том, чтобы «пометить строку» таким образом, чтобы «метка» была удалена, когда транзакция, которая применила метку, была зафиксирована, и блокировка казалась лучшим способом сделать это. , поскольку эта таблица не читается иначе, кроме как этими потоками. Если бы я использовал флаг IsProcessed в качестве блокировки, то, вероятно, мне нужно было бы сначала выполнить обновление, а затем выбрать только что обновленную строку, но мне нужно было бы использовать флаг NOLOCK, чтобы узнать, установил ли какой-либо другой поток флаг на ряд.
Все звучит немного грязно. Самым простым вариантом было бы вообще отказаться от режима изоляции моментальных снимков, но дизайн шага № 3 требует этого.
Какие-нибудь яркие идеи о том, как лучше решить эту проблему?