Одновременное множественное обращение к строке- помогите решить (MySql4.1)
Камрады! Кто шарит- подмогните.
Есть базка. Вней таблички, в табличках, естессн, строки. Строки надо брать софтинкой, обрабатывать и по результату обработки ставить в этой строке тот или иной флаг (апдейтить, короче); Строка имеет признак того, что она обработанная или необработанная- флажочег, опятьже.. Софтинка берет необработанные и после действа помечает их как обработанные.. Обработка это- процесс ресурсоёмкий, посему экземпляров обработчика (запущенных софтинок) должно быть много. Например 5. Или 100. Табличка большая- на мильён строк (тоесть это в идеале, если не в идеале- то если не получится работать с большой, буду както чистить, чтоп была маленькая). Кроме обработчиков, которые обращаются к табличке, есть еще источники, которые в эту табличку строки заносят (создают новые); Вопрос: как реализовать с максимально возможным сохранением производительности алгоритм взятия строки на обработку отдельным экземпляром обработчика, чтобы не было конфликтов с другими экземплярами. Лочить таблицу очень не хочется. Это не путь самурая. Хочется как нить хитровыпендрицца :) Всю голову сломал, ничё путного не придумал. Поможите, люди добрые! :) |
каждому обработчику присвоить кратность, брать кол-во строк из таблицы делить на число обработчиков, и пусть каждый в своей зоне шарахается. как-то так.
|
Цитата:
Насчет кратности- количество строк постоянно меняется. Оно увеличивается или уменьшается. Причем не обязательно с краев таблички. Поэтому хочется придумать алгоритм "залочивания" строки за обработчиком. |
ну тогда можно прямо так и указать, к какому обработчику эта строка относится, тогда совсем без лока будет, а при добавлении строки ставить индекс обработчика по кругу. Не передерутся.
|
Цитата:
Но: 1. Обработчики разноскоростные с одной стороны и обработка одной строки идет не стандартное количество времени (строки разные)- получится что ктото будет простаивать; 2. Хочется иметь возможность легкого добавления нового обработчика, не завязывая его на регистрацию гдето "на главном компутере"- тоесть поставил новый обработчик, указал ему в конфиге адрес и пароль к базке- и он пошел колбасить.. Или взял, остановил, обработчик и выкинул его. И нигде не нужно их прописывать.. Как считаете? Так можно сделать? Или это слишком жырно? :) |
Йода, таблица MyISAM? создайте аналог InnoDB, там встроена построчная блокировка.
или даже в MyISAM можно лишний столбец - флажок (три позиции! 0 незаблокировано, 1 чтение (не записывать), 2 запись (доступ закрыт)) блокировки строки сделать. |
Последний Герой, про инно-дб, да. Надо пошукать, что у них там с транзакциями..
А вот насчет Цитата:
:) |
Цитата:
SELECT ... FROM ... WHERE ... [FOR UPDATE | LOCK IN SHARE MODE] [COMMIT|ROLLBACK] FOR UPDATE - блокирует строку на мертво LOCK IN SHARE MODE - разрешает другим процессам только читать строку COMMIT - завершить транзакцию с сохранением данных ROLLBACK - завершить транзакцию с удалением данных (откат) Цитата:
1) добавляете столбец числовой и обнуляете его значение для ВСЕХ строк 2) как только какой то поток хочет обратиться к строкам, он записывает в столбец свой айди, с условием, что столбец равен нулю (примерно так UPDATE SET столбец=айди WHERE столбец=0) 3) далее он считывает столбец, если блокировку удалось установить, то в столбце написан его айди (иначе там либо 0 либой айди другого процесса) 4) если блокировки нет, то возвращаемся к шагу 2 5) если блокировка есть, то можно считать, что строки заблокированы и выполнять с ней любые махинации 6) снимаем блокировку, записывая в столбец 0 |
Делить таблицу на равные куски плохо т.к. на миллионе параллельных потоков, даже если все операции одинаково ресурсоемки, всегда найдутся процессы, которые сделают их в 3 раза быстрей чем самый медленный. Это обусловлено внешними факторами, неравномерностью распределения процессорного времени и т.д.
Поэтому к концу работы у вас получится что 2 потока "догрызают" последние 10 000 записей, в то время как остальные 98 уже стоят. Т.е. производительность к концу работы будет заметно снижаться. Простой и эффективный способ есть такой: 1) В таблицу вводим доп поле `handler`. 2) Каждому процессу присваиваем уникальный идентификатор (например, порядковый номер) 3) Делаем Код:
UPDATE `table` SET 4) Выбираем эту строчку через Код:
SELECT .... WHERE `handler`=<идентификатор текущего процесса> 5) по завершению ставим записи is_processed = 1 Для оптимизации можно резервировать по 10-30 записей за раз, тогда будет меньше накладных расходов на обращение к БД. Для легкого добавления обработчика сделайте это поле, например, строковым и пишите туда не число, а типа `mycomputer-1` и т.д. В общем, неймспейсы:) Совершенно пофигу как и в каком порядка они будут называться. Не забудьте только индекс на это поле поставить. |
Alexey, у вас частный случай моего предложения, только в вашем случае к строке может обращаться всего 1 поток и только 1 раз. ТСу же нужны построчные блокировки для нескольких обращений, как это реализовано в иннодб.
|
Часовой пояс GMT +3, время: 16:12. |
Работает на vBulletin® версия 3.8.7.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
SAPE.RU — система купли-продажи ссылок с главных и внутренних страниц сайтов.