Bloqueando una fila con SQLite (¿leer locking?)

He desarrollado un probador proxy básico en Python. Las direcciones IP y los puertos proxy, así como su date_of_last_test (por ejemplo, 31/12/2011 10:10:10) y el result_of_last_test (OK o KO) se almacenan en una sola tabla SQLite. (Me doy cuenta de que podría almacenar muchos más detalles sobre los resultados de las pruebas y mantener un historial / estadísticas, pero este modelo simple se adapta a mis necesidades).

Aquí está el código simplificado del bucle principal del comprobador, donde hago un bucle sobre los proxies y actualizo su estado:

 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') 

Mi código funciona bien cuando se ejecuta como un solo proceso. Ahora, me gustaría poder ejecutar muchos procesos del progtwig, utilizando el mismo archivo de base de datos SQLite . El problema con el código actual es la falta de un mecanismo de locking que impida que varios procesos prueben el mismo proxy.

¿Cuál sería la forma más limpia de poner un candado en la fila en el momento del PASO 1 / SELECCIONAR , de modo que el siguiente proceso que realice una SELECCIÓN obtenga la siguiente fila?


En otras palabras, me gustaría evitar la siguiente situación:

Digamos que son las 10PM, y la base de datos contiene 2 proxies: Proxy A probado por última vez a las 8PM y proxy B probado a las 9PM.

Comienzo dos procesos del probador para actualizar sus estados:

  • 10:00 – Proceso 1 obtiene el proxy “más antiguo” para probarlo: A
  • 10:01 – El proceso 2 obtiene el proxy “más antiguo” para probarlo: !!! A !!! (aquí me gustaría que el Proceso 2 obtuviera el proxy B porque A ya se está probando, aunque todavía no se ha actualizado en db)
  • 10:10 – La prueba de A by Process 1 ha terminado, su estado se actualiza en DB
  • 10:11 – La prueba de A by Process 2 ha terminado, su estado se actualiza (¡¡¡DE NUEVO !!!) en DB

No hay un error / excepción real en este caso, pero una pérdida de tiempo que quiero evitar.

SQlite solo permite que un proceso actualice cualquier cosa en la base de datos a la vez.

Varios procesos pueden tener la misma base de datos abierta al mismo tiempo. Múltiples procesos pueden estar haciendo un SELECT al mismo tiempo. Pero solo un proceso puede realizar cambios en la base de datos en cualquier momento,

y

Cuando SQLite intenta acceder a un archivo que está bloqueado por otro proceso, el comportamiento predeterminado es devolver SQLITE_BUSY. Puede ajustar este comportamiento desde el código C utilizando las funciones API sqlite3_busy_handler () o sqlite3_busy_timeout ().

Por lo tanto, si solo hay algunas actualizaciones, esto funcionará de lo contrario, debe cambiar a una base de datos más capaz.

así que solo hay un locking que está en toda la base de datos