2011-05-11 7 views
14

No estoy seguro de cómo preguntar esto de manera concisa, así que lo explicaré a través del contexto situacional.Prevención de sobreescrituras simultáneas al editar una fila de MySQL a través de PHP

Usuario-A decide que quiere modificar una fila de MySQL a través de un formulario HTML. Simultáneamente, User-B decide que también quiere modificar la misma fila de MySQL de la misma manera.

diremos el MySQL-fila es un campo de texto que contiene el texto, 'Can\'t touch this'

Los dos usuarios no tienen conocimiento de eachothers intenciones.

El usuario A realiza un cambio significativo en la fila MySQL y la guarda en la base de datos. La fila MySQL se convierte en 'Can\'t touch this was a popular track by the Hip-Hop artist M.C. Hammer.'

El usuario B realiza un cambio menor en la fila MySQL y la guarda en la base de datos. El MySQL-fila se convierte en 'Cannot touch this. Please avoid contractions.'

Debido a que el usuario B decidió modificar el MySQL-fila antes de que el usuario Un terminó su modificación, la modificación del usuario-Un hecho se sobrescribe por la modificación realizada por el usuario-B.

¿Cómo lidiar con esto las secuencias de comandos que permiten la edición simultánea de filas de bases de datos (como MediaWiki o cualquier otro software wiki)?

+0

AFAIK mediawiki no permite la edición simultánea de sus documentos. La última vez que revisé indican si alguien está editando el documento y le dicen que evite hacer cambios mientras tanto. – Gal

+0

Hace unas semanas, SO permitió esta edición simultánea, sobrescribiendo sin rodeos las ediciones anteriores sin previo aviso. Por el momento, este sitio muestra un mensaje de error que alguien más editó una publicación (o propuso una edición), impidiéndome así (guardar temporalmente) un mensaje editado, permitiéndome perder tiempo y energía en una edición inútil. Por cierto, creo que intercambiaste los resultados en el penúltimo párrafo. –

+0

@sombe Ese es el método que utilicé anteriormente. Sin embargo, encontré un error ya que el cierre tenía un tiempo de expiración que los usuarios legítimamente haciendo una edición larga excederían y luego no podrían enviar porque se convirtió en libre y fue bloqueado por otra persona. – Kairu

Respuesta

5

La solución más simple es agregar al menos un campo adicional a las tablas que se pueden editar de esta manera. Algo para indicar que la fila está bloqueada. Para una mayor utilidad, debe registrar cuándo se bloqueó la fila y por quién.

También se necesitaría un trabajo programado para desbloquear los registros que fueron abandonados, de lo contrario alguien podría simplemente editar cada registro en secuencia, abandonar la edición y bloquear toda la base de datos.

Algo similar sucede aquí en SO. Si está editando la pregunta de otra persona y alguien más guarda una edición mientras está trabajando lejos, recibirá un aviso de que la pregunta ha cambiado y sus ediciones ya no son válidas.

+1

Incluso hay una desventaja para el bloqueo temporizado. Lógicamente, alguien podría estar haciendo una gran revisión que podría tomar una cantidad de tiempo mucho más allá del tiempo de expiración del cierre patronal. – Kairu

+0

Es cierto, pero luego podría usar un latido del corazón AJAX para actualizar el bloqueo. –

+0

¡Es cierto! Puedo seguir esta ruta. Por mucho que teme usar Ajax en mis scripts, tiene sus aplicaciones. ¡Ahora, solo para descubrir cómo hacerlo! – Kairu

4

Puede usar el bloqueo de nivel de fila para forzar que las ediciones se realicen en serie (en lugar de hacerlo simultáneamente). Esto es a menudo lo que querrás hacer para diseñar una manera de fusionar los cambios, te ahorrará un poco de molestia más adelante.

También ayuda si usa una variable de fecha y hora en el formulario que envía cambios de envío a su base de datos/script de procesamiento. Luego puede verificar esto en la base de datos antes de escribir en él, y si no; Darle al usuario un mensaje de que hubo publicaciones o cambios antes que el suyo ... y dejar que htem lo vea antes de comprometer el suyo.

+0

El bloqueo de nivel de fila no funcionaría en una situación basada en web, ya que la conexión de db generalmente se corta cuando finaliza la solicitud actual. El bloqueo se mantendría mientras dure la solicitud, luego se liberará y permanecerá desbloqueado hasta la próxima solicitud. Y, mientras tanto, otros usuarios pueden entrar y editar el mismo registro. –

1

Me gustó el método de Wesley Murch. También puede permitir que varios usuarios cambien el mismo documento y emplear una fusión mientras se realiza el segundo commit. Deberá retener el documento original antes de editarlo.

+0

La fusión de las revisiones suena muy intensa. Aunque, definitivamente lo intentaría si supiera por dónde empezar. – Kairu

3

Uno de los métodos más sencillos que conozco es agregar un campo de versión a la tabla. Cuando lee un registro, busca el campo de versión y lo agrega como un campo oculto a su formulario de edición. Cuando los datos se vuelven a publicar después de la edición, se busca el registro y se comprueba si el campo de versión en el archivo db coincide con el de su formulario. Si no, entonces el registro ha sido editado por otra persona mientras tanto (cómo lo maneja depende de usted). Si coincide, modifica los datos e incrementa el número de versión. O en otras palabras, una implementación básica de bloqueo optimista ...

+0

Bueno, no tengo un número de versión; pero, en cambio, guardo todas las revisiones en una tabla separada con un campo de tiempo que actúa tanto como la hora en que se agregó la revisión como la hora en que se modificó por última vez. Y estaba pensando en pasar ese valor como un campo de formulario oculto y verificar si coincide con su valor de base de datos al enviar el formulario. – Kairu

+1

Eso de hecho equivaldría a la misma funcionalidad. También tendría una manera fácil de comprobar si ha habido cambios mientras tanto (si la marca de tiempo no coincide). – wimvds

Cuestiones relacionadas