Pregunta

Estoy teniendo lo que parece ser un problema de concurrencia durante el uso de MySQL y PHP + Propel 1.3. A continuación se muestra un pequeño ejemplo del método de "salvar" de un objeto Propel.

public function save(PropelPDO $con = null) {
    $con = Propel::getConnection();
    try {
        $con->beginTransaction();
        sleep(3); // ignore this, used for testing only
        parent::save($con);
        $foo = $this->getFoo(); // Propel object, triggers a SELECT

        // stuff is happening here...

        $foo->save($con);
        $con->commit();
    } catch (Exception $e) {
        $con->rollBack();
        throw $e;
    }
}

El problema es el objeto $ foo. Digamos que tenemos dos llamadas del método de un ejemplo tras otro en un tiempo muy corto. En algunos casos, si la segunda transacción lee $ foo ...

$foo = $this->getFoo();

... antes de la primera transacción ha tenido la oportunidad de salvarlo ...

$foo->save($con);

... $ foo leído por la segunda transacción será obsoleto y ocurrirán cosas malas.

¿Cómo puedo forzar el bloqueo de la tabla de objetos Foo se almacenan en lo que las operaciones posteriores pueden leer de él sólo después de que la primera haya terminado su trabajo?

EDIT: El contexto es una aplicación web. En resumen, en algunos casos Quiero que la primera petición que hacer alguna modificación de datos (lo que ocurre entre la precarga y el ahorro de $ foo). Todas las solicitudes posteriores no deben ser capaces de hacer la modificación. Si se producirá o no la modificación depende del estado descabellada $ foo (atributo fila de la tabla). Si dos transacciones traen los mismos $ foo, la modificación se producirá el doble de lo que provoca un problema.

¿Fue útil?

Solución

cuando se carga esta fila existente para la pantalla / aplicación, cargar el LastChgDate también. al guardarlo, utilice "Y LastChgDate = thevalue ". comprobar el número de filas afectadas de la actualización, si es cero, devuelve un error "alguien ya ha salvado este disco", y el desmantelamiento y otros cambios. Con esta lógica en su lugar sólo puede guardar una fila si es el mismo que cuando se ha cargado. para las nuevas filas, insertar, esto no es necesario porque son nuevos.

Otros consejos

En MySQL, creo que se puede utilizar SELECT FOR UPDATE para llevar a cabo el bloqueo.

Otra opción es utilizar el GET_LOCK y función RELEASE_LOCK MySQL llama a crear cerraduras con nombre que usaría para controlar el acceso al recurso.

Hay algunos aspectos negativos de estos enfoques. No los he utilizado mucho a mí mismo y son MySQL específica pero que podrían funcionar para usted.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top