Блокировка строки с помощью SQLite (блокировка чтения?) - PullRequest
0 голосов
/ 31 декабря 2011

Я разработал базовый прокси-тестер на Python. IP-адреса и порты прокси, а также их date_of_last_test (например, 31.12.2011 10:10:10) и result_of_last_test (OK или KO) хранятся в одной таблице SQLite. (Я понимаю, что могу хранить намного больше деталей о результатах тестов и вести историю / статистику, но эта простая модель удовлетворяет моим потребностям).

Вот упрощенный код основного цикла тестера, где я зацикливаюсь на прокси и обновляю их статус:

while True:
    # STEP 1: select
    myCursor.execute("SELECT * from proxy ORDER BY date_of_last_test ASC;")
    row = myCursor.fetchone()

    # STEP 2: update
    if isProxyWorking(row['ip'], row['port']): # this test can last a few seconds
        updateRow(row['ip'], row['port'], 'OK')
    else:
        updateRow(row['ip'], row['port'], 'KO')

Мой код работает нормально, когда выполняется как один процесс. Теперь я хотел бы иметь возможность запускать многие процессы программы, , используя один и тот же файл базы данных SQLite . Проблема с текущим кодом заключается в отсутствии механизма блокировки, который не позволял бы нескольким процессам тестировать один и тот же прокси.

Каким был бы самый простой способ установить блокировку строки в STEP 1 / время SELECT , чтобы следующий процесс, выполняющий SELECT, получил следующую строку?


Другими словами, я бы хотел избежать следующей ситуации:

Допустим, сейчас 10 вечера, а в БД есть 2 прокси: Прокси A, протестированный в последний раз в 20:00, и прокси B, протестированный в 21:00.

Я запускаю два процесса тестера, чтобы обновить их статусы:

  • 10: 00 - Процесс 1 получает «самый старый» прокси для его проверки: A
  • 10: 01 - Процесс 2 получает «самый старый» прокси для его проверки: !!! A !!! (здесь я бы как Процесс 2, чтобы получить прокси B, потому что A уже тестируется - хотя еще не обновлен в БД)
  • 10: 10 - Тестирование A по процессу 1 статус обновлен в БД
  • 10: 11 - Тестирование A по процессу 2 более того, его статус обновляется (!!! СНОВА !!!) в БД

В этом случае нет фактической ошибки / исключения, но я хочу избежать пустой траты.

1 Ответ

1 голос
/ 31 декабря 2011

SQlite позволяет только одному процессу одновременно обновлять что-либо в базе данных. Из FAQ

Несколько процессов могут одновременно открывать одну и ту же базу данных.Несколько процессов могут выполнять SELECT одновременно.Но только один процесс может вносить изменения в базу данных в любой момент времени,

и

Когда SQLite пытается получить доступ к файлу, заблокированному другим процессом,поведение по умолчанию - возвращать SQLITE_BUSY.Вы можете настроить это поведение из кода C, используя функции API sqlite3_busy_handler () или sqlite3_busy_timeout ().

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

поэтому существует только одна блокировка, которая находится на всей базе данных

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...