Как лучше реализовать многопоток к SQLite через python(и не только)?
В базах данных не силён, поэтому возникла такая задачка. В sqlite лежит примерно 500к строк. 1к потоков обращаются к рандомным строкам, меняют один параметр, и берут другие строки. необходимо как-то разделять потоки, чтобы одна и та же строка не использовалась другими потоками. знаю что в MySQL есть SELECT FOR UPDATE, который автоматом блокирует доступ других тредов. т.е можно к примеру взять нужные данные с параметром "0", поменять его на "1", и эти строки уже не будут взяты другими потоками, или вообще ничего не делать. Есть ли что то подобное для SQlite? Знаю, еще очереди на питоне можно написать, но слишком сложно для меня. может кто сможет помочь?)
SELECT ... FOR UPDATE OF ... в SQLite не поддерживается. Это понятно, учитывая, что в SQLite блокировке строк избыточна, поскольку вся база данных итак блокируется при обновлении любого ее бита.
То есть можно посылать запросы на UPDATE с тысячи потоков, и не будет никакой ошибки и повторов? Тысяча потоков должна брать тысячу строк, изменять в них значение в одной колонке, и не должно быть такого, что два потока возьмут две одинаковых строки.
В целом, вы можете по-разному сделать. Самый простой вариант:
Добавить в запись маркер (колонку) "Обработано" и индекс на нее.
Потом, дергать случайну запись из БД (https://ruhighload.com/post/%D0%9E%D0%BF%D1%82%D0%... ) и запускать обработку.
ПО запуску в целом. Можно считывать "пачками" случайные строки (доработать запрос выше, да хоть union-ами), по 10 штук, к примеру, и запускать параллельную обработку.
Спасибо) Третий вариант почти подошел, только есть несколько не рабочих моментов. Вот этот код:
SELECT f.* FROM table
f JOIN ( SELECT RAND() * (SELECT max(id) from table) AS max_id )
AS m WHERE f.id >= m.max_id
ORDER BY f.id ASC LIMIT 1 ;
1) Для работоспособности этого кода, RAND должен возвращать рандомное число от 0 до 1. в sqlite RAND не так работает. в нём есть только RANDOM, который возвращает рандомное число от -9 до +9. следовательно, строки будут браться не верно. На крайний случай, это число можно рандомить в python, и затем передавать в запрос. Но может есть решение и в sqlite?
2) На счёт маркера (колонки) "Обработано" и индекс на нее - я так и хотел сделать. Но в этот запрос не получается вставить такое условие. вылетает ошибка. В каком месте кода нужно вставить это условие, чтоб правильно работало?
SELECT f.* FROM table
...
WHERE status = "Обработано"
...