2012-02-16 20 views
5

Tengo un problema con las sesiones en mi aplicación web python/wsgi. Existe una conexión mysqldb diferente y persistente para cada hilo en cada uno de los 2 procesos de daemon wsgi. A veces, después de eliminar sesiones antiguas y crear una nueva, algunas conexiones aún capturan las sesiones anteriores en una selección, lo que significa que no validan la sesión y solicitan el inicio de sesión nuevamente.¿Por qué algunas conexiones mysql seleccionan datos antiguos de la base de datos mysql después de eliminar + insertar?

Detalles: Las sesiones se almacenan en una tabla InnoDB en una base de datos mysql local. Después de la autenticación (a través de CAS), elimino cualquier sesión anterior para ese usuario, creo una nueva sesión (inserte una fila), confirmo la transacción y redirecciono a la página solicitada originalmente con la nueva identificación de la sesión en la cookie. Para cada solicitud, una identificación de sesión en la cookie se compara con las sesiones en la base de datos.

A veces, una sesión recién creada no se encuentra en la base de datos después de la redirección. En cambio, la sesión antigua para ese usuario todavía está allí. (Lo comprobé al seleccionar y registrar todas las sesiones al comienzo de cada solicitud). De alguna manera, me están dando resultados almacenados en caché. Intenté seleccionar las sesiones con SQL_NO_CACHE, pero no hizo ninguna diferencia.

¿Por qué recibo los resultados de la caché? ¿Dónde más podría ocurrir el almacenamiento en caché y cómo puede detenerlo o actualizar el caché? Básicamente, ¿por qué las otras conexiones no pueden ver los datos recién insertados?

Respuesta

9

MySQL se establece de manera predeterminada en el nivel de aislamiento "REPEATABLE READ", lo que significa que no verá ningún cambio en la transacción que se haya realizado una vez iniciada la transacción, incluso si esos (otros) cambios se han confirmado.

Si emite COMMIT o ROLLBACK en esas sesiones, debería ver los datos modificados (porque eso finalizará la transacción que está "en progreso").

La otra opción es cambiar el nivel de aislamiento para esas sesiones a "LEÍDO COMPROMETIDO". Tal vez haya una opción para cambiar el nivel predeterminado también, pero necesitaría verificar el manual para eso.

+0

Me comprometo después de la inserción (editado arriba). ¿Quiere decir que también debería comprometer o revertir en las otras conexiones? – jmilloy

+0

Sí, debe finalizar la transacción que está abierta de la * otra * sesión (o cambiar el nivel de aislamiento) –

+0

Genial, agregué una confirmación al comienzo de cada solicitud, y eso parece haber funcionado. Tal vez sea mejor hacerlo al final, pero en cualquier caso ... Volveré a marcar esto como correcto si se mantiene durante uno o dos días. – jmilloy

2

Sí, parece que se supone que solo realizará una única transacción y luego se desconectará. Si tiene una necesidad diferente, entonces necesita evitar esta suposición. Como se menciona en @a_horse_with_no_name, puedes poner un commit (aunque usaría un rollback si no estás cambiando los datos). O puede cambiar el nivel de aislamiento en el cursor - desde this discussion utilicé esta:

dbcursor.execute("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")

o, parece que se puede establecer de automóviles se comprometen a verdadera en la conexión:

dbconn.autocommit(True)

Aunque, de nuevo, esto no se recomienda si realmente se realizan cambios en la conexión.

+1

Tuve que usar 'db.autocommit (True)' incluso cuando solo estaba haciendo 'select's y las tablas subyacentes se estaban cambiando fuera de mi script. – thedude

Cuestiones relacionadas