У меня есть база данных, заполненная строками и несколькими потоками, которые обращаются к этим строкам, вводят некоторые данные из них в функцию, производя вывод, а затем заполняя отсутствующие столбцы строки с выходом.Как «блокировать» обрабатываемые строки базы данных
В этой строке: Каждая строка имеет флаг unprocessed
, который по умолчанию является истинным. Поэтому каждый поток ищет строки с этим флагом. Но каждый поток получает САМУЮ строку, получается ... потому что строка помечена как обработанная после завершения работы потока, что может произойти через несколько секунд.
Один из способов избежать этого - вставить флаг currently_processed
для каждой строки, пометить его как false, и как только поток обратится к строке, измените ее на true. Затем, когда поток будет выполнен, просто измените, если он вернулся к false. Проблема в том, что я должен использовать какую-то блокировку и не позволять никому другому потоку ничего делать, пока это не произойдет. Мне было интересно, есть ли альтернативный подход, когда мне не нужно будет блокировать потоки (через мьютекс или что-то еще) и тем самым замедлить весь процесс.
Если это помогает, код находится в Ruby, но эта проблема является агностикой языка, но вот код, демонстрирующий тип потоков, которые я использую. Так что ничего особенного, резьб на самом низком уровне, как почти во всех языках есть:
3.times do
Thread.new do
row = get_database_row
result = do_some_processing(row)
insert_results_into_row(result)
end
end.each(&:join)
В то время, как в процессе трансляции другие потоки должны ждать, верно? Я не вижу, как это отличается от мьютекса. Ofc, это на уровне базы данных, но есть ли какая-либо функциональная разница? – anemaria20
Ваш * mutex * - это то, что живет в вашем приложении. Как написано: вы не можете предположить, что чтение двух чтений, чем запись этого поля ** в **, приведет к правильным результатам. Да, вам не нужно использовать базу данных, но дело в том, что это одна из точек использования базы данных - с этим уровнем контроля. Понимаете, вы просто предлагаете ** пересоздать ** колесо здесь, в вашем приложении. У вас есть шансы: вы получите это неправильно. – GhostCat
@ anemaria20: реальный мьютекс будет работать, но ваше исходное описание флага 'current_processed' не будет работать. Флаг 'current_processed' может выглядеть как мьютекс, но мьютекс обладает дополнительным свойством: есть гарантии низкого уровня, что ни один из двух потоков не может одновременно устанавливать mutex. Аналогичным образом транзакции представляют собой функцию БД, которая предоставляет такие гарантии. Таким образом, транзакции в основном состоят в том, как базы данных предоставляют возможности, подобные mutex. – slebetman