Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

Presentación y consulta

Estas en el tema de Presentación y consulta en el foro de Mysql en Foros del Web. Hola: Soy nuevo en el foro y he llegado a él buscando una respuesta a la cuestión de la concurrencia. He mirado en el área ...
  #1 (permalink)  
Antiguo 01/10/2014, 04:07
 
Fecha de Ingreso: octubre-2014
Ubicación: Bilbao
Mensajes: 14
Antigüedad: 9 años, 7 meses
Puntos: 0
Presentación y consulta

Hola:

Soy nuevo en el foro y he llegado a él buscando una respuesta a la cuestión de la concurrencia. He mirado en el área de faq pero no he encontrado nada de este tema y no he visto o no he sabido encontrar algo como un formulario para hacer búsquedas en una base de datos del foro donde se pueda hacer búsquedas por temas.

Mi pregunta es la siguiente: ¿Cómo resuelven en php y mysql el problema de la concurrencia a la hora de modificar datos en una base de datos de mysql? Es decir, el usuario1 hace las siguientes operaciones:

1. Recupera un registro de una tabla de la bd (select).
2. Rellena los campos de un formulario de edición con esos datos.
3. Modifica los campos del formulario.
4. Guarda los nuevos datos en la bd (update).

En lo que va del paso 1 al paso 4 el usuario2 accede al mismo registro y lo borra, o bien hace su propio update antes de que el usuario1 acabe. Con lo cual:

Cuando el usuario1 intente hacer el update se producirá un error o se cargará la modificación que halla hecho el usuario2.

Inicialmente pensé en usar un semáforo o flag que indique si ese registro está tomado o está siendo editado por otro usuario y, si es así, que no permita modificalo. Pero eso no resuelve el problema, ya que:

1. compruebo si el semáforo está en verde (select).
2. Si está en verde recupero los datos del registro a un formulario (select).
3. Pongo el semáforo en rojo (update).
4. Modifico los campos del formulario.
5. Modifico el registro de la tabla y pongo el semáforo en verde (update).

Entre el paso 1 y 3 otro usuario podría eliminar el registro o modificarlo. Daría igual si el paso 1 y 2 los haría en uno sólo, porque entre la comprobación a verde del semáforo y su cambio a rojo siempre mediaría un tiempo en el que se me puede meter alguien.

Muchas gracias de antemano y un saludo.
--
Agustín Sardón
  #2 (permalink)  
Antiguo 01/10/2014, 04:13
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Presentación y consulta

Primero date un paseo por el tea, en algo bastante bien explicado: http://ict.udlap.mx/people/carlos/is341/bases10.html

Luego vemos los detalles, pero te advierto que la concurrencia no se maneja en PHP, sino en la base, y usar conexiones inestables pueden alterar el comportamiento. Hacerlo con PHP puede tener problemas si las conexiones no son estables, porque la caída de una conexion a la base implica rollback a toda accion y perdida de bloqueos.
Por otro lado la concurrencia obligatoriamente requiere tablas InnoDB y no MySQM. Para lograr algo semejante con las MyISAM hay que programar algo más, y crear campos adicionales en ciertas ocasiones.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #3 (permalink)  
Antiguo 02/10/2014, 07:27
 
Fecha de Ingreso: octubre-2014
Ubicación: Bilbao
Mensajes: 14
Antigüedad: 9 años, 7 meses
Puntos: 0
Respuesta: Presentación y consulta

He estado estudiando el tema y según creo entender mysql, por defecto, tiene establecido el nivel de aislamiento para las transacciones en "repeateable read" que, de los tres problemas descritos por el SQL estándar, sólo permite la "lectura fantasma", la cual no me preocupa, porque lo que yo quiero es que ningún registro leído con un select se pueda cambiar en otra transacción, es decir, hasta que no haga un rollback o un commit.

Desde phpmyadmin ejecuto la siguiente sentencia para comprobar que el nivel de aislamiento es, efectivamente, ""repeateable read":

SHOW VARIABLES LIKE 'tx_isolation'

y el resultado es el esperado:

Variable_name Value
tx_isolation REPEATABLE-READ

Ahora escribo en la pantalla de SQL de phpmyadmin:

BEGIN;
SELECT * FROM usuario WHERE ID='65';

ejecuto y me selecciona el usuario cuyo id es 65. Ahora abro phpmyadmin en otro navegador y hago un UDATE al mismo registro de la tabla usuario. Y permite la actualización, cuando no debiera permitirla hasta que se termine la transacción que he iniciado en el otro navegador.

No entiendo qué es lo que falla o lo que estoy haciendo mal. Agradecería cualquier pista que me ilumine.

Un saludo.
Agustín
  #4 (permalink)  
Antiguo 02/10/2014, 07:49
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Presentación y consulta

Prueba así:
Código MySQL:
Ver original
  1. FROM usuario
  2. WHERE ID=65

o bien:

Código MySQL:
Ver original
  1. FROM usuario
  2. WHERE ID=65
  3. FOR UPDATE;

http://dev.mysql.com/doc/refman/5.0/...ing-reads.html
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #5 (permalink)  
Antiguo 03/10/2014, 07:47
 
Fecha de Ingreso: octubre-2014
Ubicación: Bilbao
Mensajes: 14
Antigüedad: 9 años, 7 meses
Puntos: 0
Respuesta: Presentación y consulta

La consulta me lanza el siguiente error de MySQL:

Cita:

Error

consulta SQL: Documentación

Código:
SELECT * 
FROM usuario 
WHERE ID=65 
FOR UPDATE
LIMIT 0, 25

MySQL ha dicho: Documentación
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'LIMIT 0, 25' at line 5
El motor de la tabla usuario es InnoDB. El entorno de desarrollo XAMPP (instalación reciente). LOCK IN SHARE MODE da el mismo error.

  #6 (permalink)  
Antiguo 03/10/2014, 07:59
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Presentación y consulta

Pregunta del millón...
¿Estás intentando realizar la tarea en la interfaz de phpMyadmin?
Porque en ese contexto no va a funcionar una transacción, ya que usualmente la ejecución de una query en la ventana de SQL abre y cierra una conexión, por loque la transacción se cierra con la terminación de la sentencia.
Para hacer una prueba válida debes programar por tu cuenta una aplicación en PHP y asegurarte que la conexión del bloqueo no se cierre, antes de que tu mismo, y en esa conexión, lo levantes.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #7 (permalink)  
Antiguo 03/10/2014, 11:00
 
Fecha de Ingreso: octubre-2014
Ubicación: Bilbao
Mensajes: 14
Antigüedad: 9 años, 7 meses
Puntos: 0
Respuesta: Presentación y consulta

Cita:
Iniciado por gnzsoloyo Ver Mensaje
Pregunta del millón...
¿Estás intentando realizar la tarea en la interfaz de phpMyadmin?
Así es.

Cita:
Porque en ese contexto no va a funcionar una transacción, ya que usualmente la ejecución de una query en la ventana de SQL abre y cierra una conexión, por loque la transacción se cierra con la terminación de la sentencia.
Sospechaba algo así. Lo siguiente que iba a intentar es lo que comentas:

Cita:
Para hacer una prueba válida debes programar por tu cuenta una aplicación en PHP y asegurarte que la conexión del bloqueo no se cierre, antes de que tu mismo, y en esa conexión, lo levantes.
Lo que pasa es que quería hacer una prueba, una especie de test, antes de liarme a programar. Voy a hacer dos scripts php con una transacción en cada uno. A ver qué pasa. La duda que tengo es si al terminar la ejecución de un script php que abre una transacción y no la completa hará rollback. Espero que no, que la terminación del script no produzca la finalización de la transacción. Porque eso daría al traste con un diseño MVC de la aplicación.

Comentaré cómo me ha ido.

Mil gracias y un saludo.
--
Agustín
  #8 (permalink)  
Antiguo 03/10/2014, 12:04
 
Fecha de Ingreso: octubre-2014
Ubicación: Bilbao
Mensajes: 14
Antigüedad: 9 años, 7 meses
Puntos: 0
Respuesta: Presentación y consulta

Efectivamente. Cuando termina la ejecución de un script termina la conexión, con lo cual termina también la transacción. Luego esta solución no me vale porque para modificar un registro yo tengo que:

1. hacer una lectura del registro.
2. llevar los datos de la lectura a un formulario de html.
3. el usuario tendrá que modificar los datos del formulario y al enviar el formulario
4. el action del formulario llamará a un script php.

En mi aplicación sería:

1. El controlador (un script) pide al modelo (otro script) que recupere el registro de la base de datos.
2. La vista muestra los datos en el formulario html.
3. El usuario envia el formulario modificado que llama de nuevo al controlador.
4. El controlador pide al modelo que guarde los datos en la base de datos.

En todo este proceso no es posible mantener una única conexión abierta a la base de datos y una transacción abierta.

Luego, después de todo este lio, vuelvo a mi pregunta inicial: ¿Cómo implementan una solución al problema de la concurrencia a la base de datos en una aplicación php?

  #9 (permalink)  
Antiguo 03/10/2014, 12:42
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Presentación y consulta

Cita:
¿Cómo implementan una solución al problema de la concurrencia a la base de datos en una aplicación php?
Programando...

Nadie usa phpMyadmin como gestor de datos ni como aplicación de gestión comercial. Es sólo una interfaz de acceso a MySQL de un modo amigable, pero no sirve para trabajar.

Cuando creas tu propia aplicación, tu mismo regulas todos los elementos que se necesitan. Si no quieres hacerlo siempre puedes conseguir aplicaciones prediseñadas que te sirvan.
El problema, por tanto, no está en MySQL, sino en la herramienta que usas. Eso es todo...
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #10 (permalink)  
Antiguo 03/10/2014, 14:59
 
Fecha de Ingreso: octubre-2014
Ubicación: Bilbao
Mensajes: 14
Antigüedad: 9 años, 7 meses
Puntos: 0
Respuesta: Presentación y consulta

Cita:
Programando...
¡Genial!

Cita:
Nadie usa phpMyadmin como gestor de datos ni como aplicación de gestión comercial. Es sólo una interfaz de acceso a MySQL de un modo amigable, pero no sirve para trabajar.
Como gestor de base de datos uso MySQL. phpMyAdmin lo uso como parte del entorno de desarrollo que es XAMPP y lo usa muchísima gente.

Cita:
Cuando creas tu propia aplicación, tu mismo regulas todos los elementos que se necesitan. Si no quieres hacerlo siempre puedes conseguir aplicaciones prediseñadas que te sirvan.
Claro que quiero hacerlo, en eso estoy.

Cita:
El problema, por tanto, no está en MySQL, sino en la herramienta que usas. Eso es todo...
Ya sé que el problema no está en MySQL, eso lo he entendido. En cuanto a PHP no es una herramienta es una tecnología.

Se me ha ocurrido una técnica para bloquear registros mediante programación utilizando dos campos más en cada tabla. Uno que indique si está bloqueado el registro y el otro por quién está bloqueado (id del usuario).

De esa forma cuando un usuario intente editar un registro el programa comprobará que no está bloqueado y, si está bloqueado, comprobará que el usuario que lo bloqueó es el usuario que está intentando editarlo, si no es así, no le dejará. Cuando vaya a hacer el update hará la misma comprobación.

Seria:

1. un UPDATE que ponga el campo lock a true y el campo user_lock con el id del usuario en el registro que queramos editar.

2. una SELEC de edición que comprueba si el campo lock está a false. Si no lo está comprobar que el id del usuario que lo ha bloqueado es el des mismo usuario que está logueado. Sí es así palante. En caso contrario no permitir la edición.

3. Exactamente igual a la hora de guardar los cambios.

No me gusta mucho porque es intrusivo, pero no se me ocurre otra forma.

Como ves estoy programando. Si hablo del patrón MVC, de scripts php, de cargar datos en formularios, etc. de que otra cosa podría estar hablando más que de programación. La pregunta era sencilla y la recalco "¿Cómo solucionáis el problema de la concurrencia al modificar datos en mysql desde php?" La pregunta es sencilla, la respuesta no tanto. Gracias por intentarlo.

--
Agustín
  #11 (permalink)  
Antiguo 03/10/2014, 15:14
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: Presentación y consulta

No te compliques.
En tanto uses las transacciones dentro de conexiones permanentes, MySQL resuelve el resto por medio de ellas.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #12 (permalink)  
Antiguo 04/10/2014, 03:26
 
Fecha de Ingreso: octubre-2014
Ubicación: Bilbao
Mensajes: 14
Antigüedad: 9 años, 7 meses
Puntos: 0
Respuesta: Presentación y consulta

Cita:
Iniciado por gnzsoloyo Ver Mensaje
En tanto uses las transacciones dentro de conexiones permanentes, MySQL resuelve el resto por medio de ellas.
Ahí está el problema. Mantener una conexión permaente en un lenguaje de scripting como es PHP. La conexión dura lo que dura la ejecución de un PHP, no puedes pasar el objeto conexión de un PHP a otro, lo intenté a través de la sesión, pero parece que con PHP guardar objetos en la sesión no pita, no así en Java. Y yo necesito eso porque sigo el patrón de disño MVC que para mi es muy importante. Y aunque no siguiera el patrón MVC no veo cómo sería posible mantener la conexión en el proceso de leer datos de la base de datos, llevarlos a un formulario, dar tiempo al usuario para que los modifique y los envie, y volver a guardar los datos modificados en la base de datos.

De todas formas el hilo me ha venido bien para aprender a gestionar transacciones que no había visto nunca. Pero... en PHP las transacciones han de ejecutarse en el ámbito de un sólo php, lo cual limita bastante el tema. El problema no está en MySQL, es cierto, es una limitación de PHP.

Saludos y gracias de nuevo.
--
Agustín

Etiquetas: campo, php, registro, select, sql, tabla
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 17:42.