2009-08-24 15 views
7

Estoy haciendo un script bash que interactúa con una base de datos MySQL usando el programa de línea de comandos mysql. Quiero usar bloqueos de tabla en mi SQL. ¿Puedo hacer esto?MySQL desde la línea de comandos: ¿puedo usar prácticamente LOCKs?

mysql -e "LOCK TABLES mytable" 
# do some bash stuff 
mysql -u "UNLOCK TABLES" 

La razón que pido, es debido a bloqueos de tabla única se mantienen durante la sesión, por lo que no sería el bloqueo a conocer tan pronto como sea que los acabados de los programas MySQL?

+0

¿No debería el '-u' ser' -e'? –

Respuesta

8

[EDIT]

nos tuvieron la idea básica - sólo se ejecutan una vez "mysql" , y la solución que se proporciona debería funcionar, pero dejó FIFO en el disco.

nos también fue correcto que lo estropeé: un simple "echo X >FIFO" cerrará el FIFO; Lo recordé mal. Y mis (eliminados) comentarios w.r.t. el tiempo no aplica, lo siento.

Dicho esto, no necesita un FIFO, podría usar un tubo entre procesos. Y mirando a través de mis viejos scripts de MySQL, algunos funcionó similares a esto, pero no puede dejar que los comandos escriban en stdout (sin algunos trucos de "exec").

#!/bin/bash 
(
    echo "LOCK TABLES mytable READ ;" 
    echo "Doing something..." >&2 
    echo "describe mytable;" 
    sleep 5 
    echo "UNLOCK tables;" 
) | mysql ${ARGUMENTS} 

Otra opción podría ser asignar un descriptor de archivo a la FIFO y luego ejecutarlo en segundo plano. Esto es muy similar a lo que nos hizo, pero la opción "exec" no requeriría una subshell para ejecutar los comandos bash; por lo tanto, permitiría establecer "RC" en el "otras cosas":

#!/bin/bash 
# Use the PID ($$) in the FIFO and remove it on exit: 
FIFO="/tmp/mysql-pipe.$$" 
mkfifo ${FIFO} || exit $? 
RC=0 

# Tie FD3 to the FIFO (only for writing), then start MySQL in the u 
# background with its input from the FIFO: 
exec 3<>${FIFO} 

mysql ${ARGUMENTS} <${FIFO} & 
MYSQL=$! 
trap "rm -f ${FIFO};kill -1 ${MYSQL} 2>&-" 0 

# Now lock the table... 
echo "LOCK TABLES mytable WRITE;" >&3 

# ... do your other stuff here, set RC ... 
echo "DESCRIBE mytable;" >&3 
sleep 5 
RC=3 
# ... 

echo "UNLOCK TABLES;" >&3 
exec 3>&- 

# You probably wish to sleep for a bit, or wait on ${MYSQL} before you exit 
exit ${RC} 

Tenga en cuenta que hay algunos problemas de control:

  • Este código no tiene comprobación de errores por falta de bloquear (o cualquier comando SQL dentro de "otras cosas"). Y eso es definitivamente no trivial.
  • Dado que en el primer ejemplo, "otras cosas" está dentro de una subcadena, no puede fácilmente establecer el código de retorno de la secuencia de comandos desde ese contexto.
+0

Necesitaría una sub-concha u otro engaño, si hace eco ...> $ {FIFO} mysql simplemente saldrá después del 1. comando ya que el final de escritura cierra el conducto – nos

+0

Tiene toda la razón, mi guión ganó ' t trabajo mientras que el suyo debería (pero deja el FIFO en el disco). – NVRAM

+0

Haz que "mi script original" ... – NVRAM

4

Ésta es una forma, estoy seguro de que hay una manera más fácil, aunque ..

mkfifo /tmp/mysql-pipe 
mysql mydb </tmp/mysql-pipe & 
(
    echo "LOCK TABLES mytable READ ;" 1>&6 
    echo "Doing something " 
    echo "UNLOCK tables;" 1>&6 
) 6> /tmp/mysql-pipe 
2

Un enfoque muy interesante que descubrí al analizar este tema por mi cuenta, es mediante el uso del comando SYSTEM de MySQL. No estoy todavía seguro de qué son exactamente los inconvenientes, si los hay, pero sin duda trabajar para una gran cantidad de casos:

Ejemplo:

mysql <<END_HEREDOC 
LOCK TABLES mytable; 
SYSTEM /path/to/script.sh 
UNLOCK TABLES; 
END_HEREDOC 

Vale la pena señalar que esto sólo funciona en * nix, obviamente, as does the SYSTEM command.

crédito va a Daniel Kadosh: http://dev.mysql.com/doc/refman/5.5/en/lock-tables.html#c10447

0

Otro enfoque sin los comandos mkfifo:

cat <(echo "LOCK TABLES mytable;") <(sleep 3600) | mysql & 
LOCK_PID=$! 
# BASH STUFF 
kill $LOCK_PID 

creo que la respuesta de Amr es el más simple. Sin embargo, quería compartir esto porque alguien más también puede necesitar una respuesta ligeramente diferente.

El sleep 3600 pausa la entrada durante 1 hora. Puede encontrar otros comandos para hacer que se detenga aquí: https://unix.stackexchange.com/questions/42901/how-to-do-nothing-forever-in-an-elegant-way

El lock tables SQL se ejecuta inmediatamente, luego esperará el temporizador de reposo.

Cuestiones relacionadas