как заблокировать некоторые строки, так как они не будут выбраны в другой транзакции - PullRequest
0 голосов
/ 20 января 2011

У меня есть таблица, похожая на список URL-адресов, которые я хочу посетить.На таблицу не ссылаются и не ссылаются на другие таблицы.Что мое приложение делает:

  • выбирает несколько строк из списка URL
  • запускает цикл по ним
    • запускает транзакцию
    • посещениеURL
    • уточните его
    • запустите суб-транзакцию
      • проверьте, есть ли результаты уже в первых двух таблицах (выберите)
      • , если нет,сохранить (вставить)
    • зафиксировать суб-транзакцию
    • запустить суб-транзакцию
      • проверить, есть ли результаты уже в другой таблице (выберите)
      • , если нет, сохраните его (вставьте)
    • совершите суб-транзакцию
    • обновите строку, которую я посещаю
    • совершить основную транзакцию
  • завершить цикл

Существует множество проверок ошибок, основная транзакция имеет сотни запросов (выберите и вставьте) mysql очень сильно нагружает процессор (я думаю, из-за большого журнала отката), но все это работает нормально.

Только я не могу запустить более одного экземпляраэтого пакета, потому что выбранные строки более или менее одинаковы: это означает, что я посещаю URL-адрес более одного раза в несколько секунд, что мне не нужно.

Если я перемещаю начало основноготранзакции вне цикла и выбора строк для обновления, но я не получаю мульти-параллелизм, потому что второй экземпляр не будет запускать выборку, пока основная транзакция первого экземпляра не будет зафиксирована.

ВозможноРешение состоит в том, чтобы добавить «заблокированное» поле к первой таблице, которая будет установлена ​​в истинное значение (фактически к текущей дате, поскольку я стараюсь не использовать логические значения).

Другой вариант - запустить основную транзакцию, а затем выбрать только одну.строка (для обновления) сразу (установив «предел 1» вместо 5 или 10 на данный момент).

Я не могу представить другой способ получить то, что я хочу: не выбирать заблокированные строки.

Есть идеи?

1 Ответ

1 голос
/ 21 января 2011

Звучит так, как будто вам нужна какая-то форма маркера, чтобы идентифицировать строки как «используемые», поэтому другие экземпляры не обрабатывают те же данные;Используете ли вы логический тип или тип даты не имеет значения, каким-то образом вы должны пометить используемые строки.

Вы можете сделать это через диспетчер, процесс или поток с единственным доступом к вашей таблице, и единственной работой являетсявыбрать строки и передать их другим процессам для работы.Даже в этом случае диспетчер должен будет знать, как далеко пройдут данные, которые он получил, чтобы вы вернулись к той же проблеме.

Другой способ - использовать поле, чтобы указать, что строка используется (как вы сказали,в твоем вопросе).Каждый процесс обновляет блок строк с уникальным идентификатором, выполняемым внутри транзакции для блокировки таблицы;Я бы использовал номер соединения, возвращенный из CONNECTION_ID(), чтобы пометить их, тогда вы знаете, что он уникален.

После завершения транзакции UPDATE ... WHERE connection_id IS NULL (с применением ограничения) процесс может SELECT ... WHERE connection_id = CONNECTION_ID() получитьих строки для обработки.

Когда они завершили свою работу, весь цикл начинается снова, чтобы отметить следующий набор строк, пока все не будут обработаны.

...