• Empleos
  • Sobre nosotros
  • profesionales
    • Inicio
    • Empleos
    • Cursos y retos
    • Preguntas
    • Profesores
  • empresas
    • Inicio
    • Publicar vacante
    • Nuestro proceso
    • Precios
    • Pruebas Online
    • Nómina
    • Blog
    • Comercial
    • Calculadora de salario

0

147
Vistas
Bloqueo de nivel de base de datos SQlalchemy

Me pregunto si es posible bloquear de alguna manera un par de tablas de la base de datos para escritura protegida o algo así, para evitar que otra aplicación las modifique cuando una transacción está en curso.

Ahora tengo algo como esto. Tablas A, B y C, con relaciones de uno a muchos entre ellas A->B y B->C. Esta función recibe datos de rabbitmq y actualiza A, B y/o C (generalmente solo C) o crea nuevas filas si faltan.

 Session=scoped_session(session_factory) try: foo = Session.query(A).filter(....).one() except NoResultFound: Session.remove() return try: bar = Session.query(B).filter(......).one() except NoResultFound: bar = B(field1=x, field2=y etc.) Session.add(bar) try: xyzzy = Session.query(C).filter(...).order_by(...).limit(1).one() except NoResultFound: xyzzy = C(.......) Session.add(xyzzy) foo.fieldn = var1 bar.fieldn = var2 xyzzy.fieldn = var3 etc. Session.commit() Session.remove()

Todo esto funciona bien. El problema es que tengo otro programa (una secuencia de comandos de Python completamente diferente) que realiza una limpieza a pedido. Básicamente elimina todo, desde A, B y C. Esto también funciona.

Mi primer programa falla inmediatamente después de eliminar esto:

 sqlalchemy.orm.exc.StaleDataError: UPDATE statement on table 'C' expected to update 1 row(s); 0 were matched.

Puedo detectar esta excepción y reaccionar en consecuencia, pero ¿debo hacerlo? Este problema se resolvería si pudiera en ambos programas reservar A, B y C en el nivel de la base de datos para un archivo corto. Todas estas transacciones son de corta duración. Entiendo por la documentación de sqlalchemy que una sesión también debe iniciar una transacción, pero aparentemente esto significa algo diferente a una transacción a nivel de base de datos.

Lo que parece suceder es que mi Session.query(C) encuentra una fila, pero antes de que el primer programa emita Session.commit(), el otro programa la eliminó.

Hace más de 20 años con las bases de datos de los 90 y CI siempre comenzaba una transacción con una TRANSACCIÓN DECLARA... RESERVANDO A, B, C PARA ESCRITURA PROTEGIDA; o algo así. ¿Se ha ido ahora y solo necesito capturar la excepción, o aún puedo beneficiarme del bloqueo en el nivel de la base de datos?

hannu

almost 3 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Puede realizar un bloqueo explícito de PostgreSQL con el comando LOCK :

 LOCK A, B, C IN ACCESS EXCLUSIVE MODE;

Sin embargo, bloquear tres mesas es una forma muy dura de resolver el problema. Dado que tiene una relación de 1 m, puede considerar bloquear la fila en A en su lugar, al comienzo de cada transacción:

 SELECT * FROM A WHERE ... FOR UPDATE;

La forma de hacer esto en SQLAlchemy es:

 foo = Session.query(A).filter(....).with_for_update().one()
almost 3 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Nuestro proceso Comercial
Legal
Términos y condiciones Política de privacidad
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recomiéndame algunas ofertas
Necesito ayuda