Tengo un problema de almacenamiento en caché cuando yo uso sqlalchemy.

Yo uso sqlalchemy para insertar datos en una base de datos MySQL. Entonces, tengo otro proceso de solicitud de este tipo de datos, y actualizar directamente.

Pero sqlalchemy siempre devuelve los datos en lugar de los datos actualizados. Creo que sqlalchemy caché mi solicitud … así que … ¿cómo puedo desactivar?

OriginalEl autor Zeyi Fan | 2012-04-18

6 Comentarios

  1. 38

    La causa habitual de la gente pensando que hay una «caché» en el juego, además de la habitual SQLAlchemy mapa de identidad que es local a una transacción, es que son la observación de los efectos de aislamiento de la transacción. SQLAlchemy la sesión de obras por defecto en el modo de transacción, es decir, se espera hasta que session.commit() es llamado con el fin de conservar los datos a la base de datos. Durante este tiempo, el resto de las transacciones en el progreso en otros lugares no va a ver este tipo de datos.

    Sin embargo, debido a la naturaleza aislada de las transacciones, hay un toque extra. Los demás operaciones en curso no sólo no ver a su transacción de datos hasta que se cometieron, que también la podemos ver en algunos de los casos hasta se cometen o se deshace también (que es el mismo efecto que su close() es tener aquí). Una transacción con un grado medio de aislamiento llevará a cabo en el estado que se ha cargado hasta ahora, y seguir dando de que el mismo estado local para la transacción aunque los datos reales ha cambiado – esto se llama repetible lee en el aislamiento de transacción de la jerga.

    http://en.wikipedia.org/wiki/Isolation_%28database_systems%29

    OriginalEl autor zzzeek

  2. 14

    Este problema ha sido muy frustrante para mí, pero por fin he descubierto.

    Tengo un Frasco/SQLAlchemy ejecución de la Aplicación, junto con un mayor PHP sitio. El PHP del sitio iba a escribir a la base de datos y SQLAlchemy no ser conscientes de los cambios.

    He probado el sessionmaker configuración autoflush=True sin éxito
    Traté de db_session.flush(), db_session.expire_all(), y db_session.commit() antes de consultar y NINGUNO funcionó. Todavía mostraron datos obsoletos.

    Finalmente me llegó a través de esta sección de la SQLAlchemy docs: http://docs.sqlalchemy.org/en/latest/dialects/postgresql.html#transaction-isolation-level

    Configuración de la isolation_level que funcionó muy bien. Ahora mi Frasco aplicación está «hablando» con el PHP de la aplicación. Aquí está el código:

    engine = create_engine(
        "postgresql+pg8000://scott:[email protected]/test",
        isolation_level="READ UNCOMMITTED"
    )

    Cuando el SQLAlchemy motor se inicia con el «LEER UNCOMMITED» isolation_level se llevará a cabo la «lecturas», que significa que se va a leer uncommited cambios directamente desde la base de datos.

    Espero que esto ayude


    Aquí hay una posible solución cortesía de AaronD en los comentarios

    from flask.ext.sqlalchemy import SQLAlchemy
    
    class UnlockedAlchemy(SQLAlchemy):
        def apply_driver_hacks(self, app, info, options):
            if "isolation_level" not in options:
                options["isolation_level"] = "READ COMMITTED"
        return super(UnlockedAlchemy, self).apply_driver_hacks(app, info, options)
    Si usted está usando Matraz SQLAlchemy, puede subclase flask.ext.sqlalchemy.SQLAlchemy y anular el apply_driver_hacks función para establecer el nivel de aislamiento, manteniendo todo el Frasco de integración. También, probablemente, el nivel de aislamiento de READ COMMITTED es suficiente proporcionar tanto a las aplicaciones que están cometiendo sus escrituras después de que hacen ellos y no esperar por un largo tiempo. De esa manera usted no tiene que preocuparse acerca de las lecturas – sólo le da una nueva instantánea de base de datos cada vez que usted lea.
    Podría publicar el código para la subclase flask.ext.sqlalchemy.SQLAlchemy como usted ha mencionado?
    Sólo tengo este en mi código: class UnlockedAlchemy(SQLAlchemy): def apply_driver_hacks(self, app, info, options): if not "isolation_level" in options: options["isolation_level"] = "READ COMMITTED" return super(UnlockedAlchemy, self).apply_driver_hacks(app, info, options)
    Salvavidas! Estoy usando engine_from_config a leer el sqlalchemy configuración desde archivo y simplemente he añadido: sqlalchemy.isolation_level = READ UNCOMMITTED a mi archivo de configuración y cambios externos son ahora correctamente reflejado en mi app 🙂
    Esto no tiene sentido. Si la transacción para la actualización de la base de datos está correctamente cometido (por el php del sitio), ¿por qué usted necesita para establecer el nivel de aislamiento a «READ UNCOMMITTED»? Es más como un problema de cómo su sitio PHP es la actualización de la base de datos.

    OriginalEl autor Nick Woodhams

  3. 3

    Además a zzzeek excelente respuesta,

    Yo tenía un problema similar. He resuelto el problema mediante la corta vida de sesiones.

    with closing(new_session()) as sess:
        # do your stuff

    He utilizado una nueva sesión por tarea, la tarea del grupo o de la solicitud (en el caso de la aplicación web). Que resolvió el «caché» el problema para mí.

    Este material fue muy útil para mí:

    ¿Cuándo debo construir una Sesión, ¿cuándo lo voy a cometer, y cuando la cierro

    El enlace de arriba se va a la documentación para el período de sesiones. El título implica que debe estar apuntando aquí: docs.sqlalchemy.org/en/rel_0_8/orm/…
    docs.sqlalchemy.org/en/latest/orm/…

    OriginalEl autor Jakub M.

  4. 3

    Que esto estaba ocurriendo en mi Frasco de aplicación, y mi solución fue caducar todos los objetos en la sesión después de cada petición.

    from flask.signals import request_finished
    def expire_session(sender, response, **extra):
        app.db.session.expire_all()
    request_finished.connect(expire_session, flask_app)

    Trabajó como un encanto.

    OriginalEl autor egafni

  5. 0

    Primera es que no hay caché para SQLAlchemy.
    Basado en el método para obtener los datos de DB, usted debe hacer algunas pruebas después de la base de datos es actualizada por los demás, a ver si usted puede conseguir los nuevos datos.

    (1) use connection:
    connection = engine.connect()
    result = connection.execute("select username from users")
    for row in result:
        print "username:", row['username']
    connection.close()
    (2) use Engine ...
    (3) use MegaData...

    por favor, siguiendo el paso en : http://docs.sqlalchemy.org/en/latest/core/connections.html

    Otra posible razón es que tu base de datos MySQL no se actualiza de forma permanente. Reiniciar el servicio de MySQL y tengo un cheque.

    Gracias por la respuesta. Yo lo he solucionado. Me acaba de olvidar session.close cuando yo uso scoped_session

    OriginalEl autor wuliang

  6. -1

    Como sé SQLAlchemy no almacena almacena en caché, por lo que necesita para mirar el registro de de salida.

    Yo así lo cree. Abrí echo = True pero no tengo nada útil.
    tienen que actualizar la sesión con un commit?
    Puedo actualizar los datos sin el uso de sqlalchemy.. uso MySQLdb.. I asegurar que los datos se han actualizado en MySQL..
    intenta establecer la confirmación automática a la Verdad en su sessionmaker (bind=auto.motor, autocommit=True)
    Gracias por la respuesta. Yo lo he solucionado. Me acaba de olvidar session.close cuando yo uso scoped_session. débil..

    OriginalEl autor Voislav Sauca

Dejar respuesta

Please enter your comment!
Please enter your name here