Вы находитесь на странице: 1из 41

Stored Procedures y Stored Functions en MySQL

MySQL, como todo producto profesional de bases de datos, ofrece la posibilidad de


almacenar instrucciones en la propia base, de forma de invocar ese bloque de código
desde una aplicación por medio de un nombre. Eventualmente, a ese bloque se le
pueden enviar parámetros.

Esas instrucciones pueden ser una simple instrucción de SQL, o bien complejos
bloques de código, con variables, condicionales, repetitivas, y tal (a diferencia
de Access, donde las Queries pueden contener una única instrucciónSQL).

Existen en MySQL tres clases de componentes al respecto, cuya funcionalidad es,


en los tres casos, básicamente la misma: almacenar en la base un subconjunto de
la lógica de un sistema, bajo un nombre, de forma que cualquier consumidor de la
base de datos pueda utilizarlo.

Estos tres componentes son las vistas (Views), las funciones almacenadas (Stored
Functions) y los procedimientos almacenados (Stored Procedures). Los Stored
Procedures y las Stored Functions se agrupan en un conjunto llamado rutinas
(Routines).

Las vistas no nos interesan demasiado, ya que no sirven para el uso que solemos
darle a las bases de datos, así que vamos a concentrarnos en los otros dos
elementos.

Los Stored Procedures son más parecidos a las Queries de Access: permiten
almacenar instrucciones SQL, tanto de lectura como de escritura, guardados bajo
un nombre, y ejecutarlos desde C#. Puede recibir parámetros para ser utilizados
en la ejecución.
Si bien un Stored Procedure de MySQL puede almacenar un gran bloque de
instrucciones, en nuestro primer ejemplo vamos a crear y utilizar un SP simple con
una instrucción única, con parámetros.

Comenzamos por conectarnos a la base de datos por medio del Workbench, y


vamos al sector Routines para crear un SP.

Ahi debemos elegir si queremos crear un Stored Procedure o una Stored


Function. Elegimos la primera, para acceder a la pantalla de edición del SP.
En esa pantalla, primeramente vamos a modificar el nombre del Stored
Procedure. Predeterminadamente se llama new_procedure, pero nosotros
vamos a llamarlo TodosLosLibros. Además, en esos paréntesis vacíos, vamos a
indicar que ese SP va a recibir un parámetro de tipo Integer. Por último, entre
el Begin y el End, vamos a escribir nuestro SQL.

He aquí el producto terminado.


Cómo probamos si funciona correctamente desde el propio MySQL, como lo
hacíamos en Access? Una vez que grabamos el SP, abrimos una nueva solapa de
consulta con File -> New Query Tab e invocamos al SP que acabamos de crear.

La instruccion call indica que estamos efectuando una llamada a una SP. Es
obligatorio indicar el nombre de la base a la que pertenece el SP que estamos
invocando. Y, desde luego, el parámetro que le mandamos.

Ejecutado eso, vemos en la solapa inferior el resultado, y verificamos su correcto


funcionamiento.

Ahora vamos a crear una Stored Function. En qué se diferencia una función
almacenada de un procedimiento almacenado?

Las funciones devuelven un único valor simple: un integer, un string, o algo


similar. Los procedures, en cambio, sirven para realizar tareas (agregar, modificar
o borrar registros), o devolver resultados en forma de tablas, como en el ejemplo
del SP que creamos arriba.
Por lo tanto, al declarar una función almacenada, debemos indicar el tipo de dato
que esa función devuelve, y en algún punto del código, efectuar esa devolución. Muy
similar a lo que hacemos con una función de un lenguaje de programación.

Entonces, vamos a comenzar por crear una función, en forma similar a como hicimos
con el SP, yendo a la seccion Routines de la base de datos, y eligiendo Create
Function.

Vamos a hacer una función que reciba como parámetro el código de un libro, y
devuelva su título.

En forma similar a lo que hicimos cuando creamos el SP, primeramente,


modificamos el nombre predeterminado de la funcion new_function por el que
queremos ponerle. En nuestro caso, será TituloLibro.
El siguiente paso es indicarle el parámetro que va a recibir la función y su tipo. Le
indicamos que recibe un parámetro que llamaremos CodigoABuscar, que será de
tipo Int.

Luego, indicamos el tipo de dato que la función devolverá. En nuestro ejemplo,


vamos a elegir Varchar (recordemos pronunciar correctamente la primera letra del
tipo de datos para evitar situaciones indeseables).
Ahora, vamos escribir el código de la función propiamente. Primero vamos a
declarar una variable de uso interno, en la que almacenaremos el valor a devolver.

Segundo, vamos a escribir el SQL que obtiene el resultado. En ese SQL, usamos
el into para asignar el campo que queremos a la variable a devolver.
Por último, en el Return, indicamos la variable que contiene el resultado a devolver.

Luego de grabar, probamos su funcionamiento, en una nueva pestaña de Query:


Al ejecutar esa línea, veremos el resultado.

Todo muy lindo, pero qué pasa si la función recibe como parámetro un código de
libro que no existe? Si aún siguiéramos en Access no podríamos hacer nada
útil. Pero no estamos más en Access, verdad?

Si el código no existe, la variable Devolver fue declarara pero no fue asignada, por
lo que quedó en null. Estaría buenísimo que pudiéramos hacer que, en tal caso, la
función devuelva un string predeterminado.

Para eso, utilizamos la ayuda de una función llamada ifnull. Esta función es muy
simple: recibe dos parámetros, y evalúa el primero de los dos. Si ese primer
parámetro no es null, la función devuelve ese mismo valor recibido. Pero si ese
primer parámetro es null, entonces devuelve lo recibido como segundo parámetro.

Hela aquí en acción:

Lo que hacemos es asignarle a la variable Devolver el resultado de la función ifnull.


A esa función le envíamos la propia variable Devolver, y un string. Si la
variable Devolver no es null, entonces la función devuelve el mismo valor que
recibe. Por lo tanto, a Devolver se le asigna Devolver, es decir, no cambia de
valor.

En cambio, si Devolver es null, la función devuelve "No encontrado", y


a Devolver se le asigna ese string.

Podemos volver a una solapa de Query para confirmar la veracidad de mis palabras.

Aquí terminamos del lado de MySQL. Ahora, vamos a C# para acceder a todos
estos procesos. Síganme, síganme, pasen por aquí.

Crear Procedimientos Almacenados en


MySQL
junio 12, 2014 James Revelo

Un procedimiento es un conjunto de instrucciones que se guardan en el servidor para un


posterior uso, ya que se ejecutarán frecuentemente. En MySQL se nombran con la
clausula PROCEDURE.
A diferencia de las funciones, los procedimientos son rutinas que no retornan en ningún tipo
de valor. Simplemente se llaman desde el cliente con un comando y las instrucciones dentro
del procedimiento se ejecutarán.
Ventajas de usar Procedimientos en MySQL
 Seguridad: Los procedimientos ocultan el nombre de las tablas a usuarios que no tengan
los privilegios para manipular datos. Simplemente llaman los procedimientos sin conocer la
estructura de la base de datos.
 Estándares de código: En un equipo de desarrollo usar el mismo procedimiento permite
crear sinergia en las fases de construcción. Si cada programador crea su propio
procedimiento para realizar la misma tarea, entonces podrían existir problemas de
integridad y perdida de tiempo
 Velocidad: Es mucho mas fácil ejecutar un programa ya definido mediante ciertos
parámetros, que reescribir de nuevo las instrucciones.
Crear un Procedimiento en MySQL
La creación de un procedimiento se inicia con las clausulas CREATE PROCEDURE. Luego
definimos un nombre y los parámetros que necesita para funcionar adecuadamente. Veamos
su sintaxis:

CREATE PROCEDURE nombre ([parámetro1,parámetro2,...])


[Atributos de la rutina]
BEGIN instrucciones
END

Un procedimiento puede tener uno o mas parámetros o también no tener ninguno. Puede
carecer de atributos o puede poseer varios. Y como ves, el cuerpo del procedimiento es
un bloque de instrucciones definido.
Parámetros de Entrada y Salida en un Procedimiento
Un parámetro es un dato necesario para el funcionamiento del procedimiento, ya que
contribuyen al correcto desarrollo de las instrucciones del bloque de instrucciones.

Los parámetros pueden ser de entrada (IN), salida (OUT) o entrada/salida (INOUT) y deben
tener definido un tipo. Un parámetro de entrada en un dato que debe ser introducido en la
llamada del procedimiento para definir alguna acción del bloque de instrucciones.
Un parámetro de salida es un espacio de memoria en el cual el procedimiento devolverá
almacenado su resultado. Y un parámetro de entrada/salida contribuye tanto como a
ingresar información útil como para almacenar los resultados del procedimiento. Por defecto,
si no indicas el tipo de parámetro MySQL asigna IN.
Para especificar el tipo de parámetro seguimos la siguiente sintaxis:

[{IN|OUT|INOUT} ] nombre TipoDeDato

Atributos de un Procedimiento en MySQL


Son características adicionales para establecer la naturaleza del procedimiento. Veamos la
utilidad de algunas:

LANGUAGE SQL: Indica que el procedimiento se escribirá en lenguaje estándar SQL/PSM.


Pero su utilidad se basa en la suposición de que en el futuro los procedimientos podrían ser
escritos en otros lenguajes como Php, Java, etc. Ya que aun los escribimos en SQL entonces
no es necesario ponerlo.
SQL SECURITY {DEFINER|INVOKER}: Establece el nivel de seguridad de invocación de un
procedimiento. Si usas DEFINER el procedimiento sera ejecutado con los permisos del usuario
que lo creó, y si usas INVOKER será ejecutado con los permisos del usuario que lo esta
invocando.
[NOT] DETERMINISTIC: Especifica si el procedimiento devolverá siempre el mismo resultado
al ingresar los mismo parámetros. O si devolverá distintos resultados al ingresar los mismo
resultados. Un ejemplo sería ingresar la suma 1+2, se sabe que siempre el resultado será 3,
así que usamos DETERMINISTIC. Pero si el parámetro es un valor de un retiro de cuenta
bancaria, el resultado del saldo que queda será diferente sin importar la cantidad retirada.
NO SQL|CONTAINS SQL|READS SQL DATA|MODIFIES SQL DATA: Estas características
determinan la estructura del procedimiento. NO SQL indica que el procedimiento no contiene
sentencias del lenguaje SQL. READS SQL DATA especifica que el procedimiento lee
información de la base de datos mas no escribe datos. MODIFIES SQL DATA indica que el
procedimiento escribe datos en la base de datos. CONTAINS SQL es el tipo por defecto de un
procedimiento e indica que el procedimiento contiene sentencias SQL
COMMENT cadena: Con este atributo podemos añadir una descripción al procedimiento con
respecto a las instrucciones que ejecuta. Por ejemplo,“Este procedimiento da de baja a todos
los clientes que hace 3 meses no compran a la compañía”.
Ejemplo de un Procedimiento con un parámetro IN
En el siguiente ejemplo desarrollemos un procedimiento para el siguiente requerimiento:

Imprima los números del 1 hasta n, donde n esta dado por el usuario.
Usaremos un procedimiento para capturar el numero n del usuario. Incorporaremos una
variable contadora que comience en 1 y un WHILE para el incremento e impresión. Veamos:

DELIMITER //

CREATE PROCEDURE numeros_1_hasta_n (IN n INT)


BEGIN
DECLARE contador INT DEFAULT 1;
WHILE contador<=n DO
SELECT contador;
SET contador = contador + 1 ;
END WHILE;
END//
DELIMITER ;

La sentencia DELIMITER cambia el carácter de terminación ';' por cualquier otro carácter,
en este caso elegimos '//'. Se hace con el fin de que MySQL no termine el procedimiento
al encontrar el primer punto y coma. Al final restablecemos el valor original del caracter de
escape.
¿Como ejecuto un procedimiento ya almacenado?
Usaremos el comando CALL enseguida del nombre del procedimiento y si tiene parámetros,
entonces se ingresan sus parámetros. Ahora veamos como llamar al anterior procedimiento:

CALL numeros_1_hasta_n(5)

Veamos el resultado:

Modificar un Procedimientos en MySQL


Para modificar un procedimiento en MySQL usaremos la sentencia ALTER PROCEDURE. Esta
modificación permite cambiar el nivel de seguridad y la descripción del procedimiento.

ALTER PROCEDURE nombre


[SQL SECURITY {DEFINER|INVOKER}]
[COMMENT descripción]
Ejemplo: Cambiar la descripción de un Procedimiento
A continuación mostraremos un procedimiento que inserta un cliente en la base de datos.

DELIMITER //
CREATE PROCEDURE insertar(id_cliente INT, nombre_cliente VARCHAR(100), apellido_cliente
VARCHAR(100))
COMMENT 'Procedimiento que inserta un cliente a la base de datos'
BEGIN
IF NOT EXISTS ( SELECT C.ID
FROM CLIENTE AS C
WHERE C.ID = id_cliente) THEN
INSERT INTO CLIENTE(ID, NOMBRE, APELLIDO)
VALUES ( id_cliente,nombre_cliente,apellido_cliente);
ELSE
SELECT 'Este cliente ya existe en la base de datos!';
END IF;
END//

DELIMITER ;

Ahora le cambiaremos la descripción mediante ALTER PROCEDURE:

ALTER PROCEDURE insertar_cliente


COMMENT 'Insertar Cliente'

Borrar un Procedimiento en MySQL


La sentencia DROP permite borrar un procedimiento de MySQL. Obviamente el
procedimiento debe estar almacenado con anterioridad para poder llevar a cabo la operación.
Dado el caso de que no se encuentre creado, podemos usar el operador EXISTS junto al
condicional IF para comprobar su existencia.

DROP PROCEDURE [IF EXISTS] nombre_procedimiento

Ejemplo: Eliminar un Procedimiento antes de crearlo


La eliminación de un procedimiento se lleva a cabo con DROP PROCEDURE. Es común usa esta
sentencia antes de crear un procedimiento.
Como ejemplo crearemos un procedimiento llamado mostrar_clientes, el cual
simplemente consulta todas las columnas de una tabla llamada CLIENTE:
DROP PROCEDURE IF EXISTS mostrar_clientes;
CREATE PROCEDURE mostrar_clientes()
SELECT * FROM CLIENTE;

Si el procedimiento que deseamos crear ya existe, entonces lo borraremos para darle paso a
la nueva definición.

Mostrar un Procedimiento en MySQL


Para mostrar las características de un procedimiento en MySQL usaremos la
sentencia SHOW CREATE PROCEDURE.

SHOW CREATE PROCEDURE nombre_procedimiento

Podrías mostrar un ejemplo?


Por supuesto!, a continuación mostraremos las características de
un procedimiento llamadoHELLOWORLD que se encuentra gestionado
por phpMyAdmin de XAMPP.

------------ ------------------------- --------------------


----------------- ------------------- --------------------------
------------ ---------------------- -------------------------
SQL JOIN
La instrucción SQL JOIN se utiliza para combinar dos o más tablas,
tomando un campo común de las dos.

El JOIN más común es: SQL INNER JOIN (join simple). Un SQL INNER
JOIN devuelve todos los registros de varias tablas que cumplen con la
condición.

SINTAXIS INNER JOIN


SELECT column_name(s)
FROM table1
INNER JOIN table2
ON table1.column_name=table2.column_name;
ó
SELECT column_name(s)
FROM table1
JOIN table2
ON table1.column_name=table2.column_name;
INNER JOIN es lo mismo que JOIN.

Ejemplo INNER JOIN


En nuestro ejemplo combinamos todos los registros de las tablas
"publisher" y "books" cuando se cumple con la condición
books.idpublisher=publisher.idpublisher.
SQL LEFT JOIN
La claúsula LEFT JOIN devuelve todas los registros de la tabla de la
izquierda (table1), con las correspondientes de la tabla de la derecha
(table2). El resultado es NULL en la parte de la derecha cuando no hay
registros que correspondan con la condición.

SINTAXIS SQL LEFT JOIN


SELECT column_name(s)
FROM table1
LEFT JOIN table2
ON table1.column_name=table2.column_name;

en algunas bases de datos LEFT JOIN es LEFT OUTER JOIN;

SELECT column_name(s)
FROM table1
LEFT OUTER JOIN table2
ON table1.column_name=table2.column_name;
Ejemplo SQL LEFT JOIN

Aquí podemos ver que el resultado es el mismo que el INNER JOIN pero
esto es porque todos los registros de "books" tienen un "idpublisher" que
coincide con un "idpublisher" de la tabla "publisher". Si insertamos un
nuevo registro en la tabla "books", con un "idpublisher" que no coincida
con ningun "idpublisher" de la tabla "publisher" (idpublisher=0) entonces;
cuando escribimos nuestra consulta LEFT JOIN no vamos a obtener ningún
registro de la tabla "publisher";

Claúsula RIGHT JOIN


La instrucción RIGHT JOIN devuelve todas los registros de la tabla de la
derecha (table2), y todas los registros correspondientes de la tabla de la
izquierda (table1). El resultado será NULL cuando no haya registros
correspondientes de la tabla de la izquierda.
SQL RIGHT JOIN Syntax
SELECT column_name(s)
FROM table1
RIGHT JOIN table2
ON table1.column_name=table2.column_name;

SELECT column_name(s)
FROM table1
RIGHT OUTER JOIN table2
ON table1.column_name=table2.column_name;

Ejemplo SQL RIGHT JOIN


Podemos cambiar en la consulta SQL, el orden de las tablas para que
veamos que es lo mismo que el LEFT JOIN pero al revés:
----------- ------------- ------------ --------------
--------- -------------- --------------
------------------ ----------- ----------------

FUNCIÓN SQL LEFT


Retorna la parte izquierda de un string a partir del número de caracteres
especificado.

SINTAXIS FUNCION SQL LEFT


LEFT ( character_expression , integer_expression )

1. "Character_expression" es una expressión de caracteres o de datos binarios.


Puede ser una constante, variable o una columna.
2. "Integer_expression" es un integer positivo que especifica los caracteres que
retornará de "character_expression".
EJEMPLO DE LA FUNCIÓN SQL LEFT
Como vemos en la tabla "books", el nombre de los autores no empieza
siempre con mayúscula. Vamos a cambiarlo, para esté bien escrito.

Aquí vemos la columna "author";

Y a continuación vemos como, la función LEFT(), retorna la primera letra


de la columna "author", que en este caso es la letra "e";
FUNCIÓN SQL UPPER
La función UPPER() convierte el valor del campo a mayúscula.

SINXTAXIS DE LA FUNCIÓN SQL UPPER


SELECT UPPER(column_name) FROM table_name;
Ejemplo de la función SQL UPPER
Una vez que tenemos la primera letra del autor, queremos que esté en
mayúsculas y esto lo conseguimos con la siguiente instrucción;

FUNCIÓN SQL SUBSTRING


La función SUBSTRING() retorna el substring especificado.

SINTAXIS DE LA FUNCIÓN SQL SUBSTRING


SUBSTRING (string, position, [length])
Donde "position" y "length" son integers. Esta sintaxis dice; retornar el
substring dado desde el caracter en la posición indicada (position), con la
longitud indicada (length).

En MySQL y Oracle, la longitud (length) es un argumento opcional.


Cuando "length" no se especifica, se retorna el string completo a partir
del caracter en la posición indicada.

EJEMPLO DE LA FUNCIÓN SQL SUBSTRING


A continuación vemos como la función devuelve todo el string, de la
columna "author", a partir de la segunda letra:
FUNCIÓN SQL LOWER
La función LOWER() retorna una expresión de caracteres convertida de
mayúsculas a minúsculas.

SINTAXIS DE LA FUNCIÓN SQL LOWER


SELECT LOWER(column_name) FROM table_name;
EJEMPLO DE LA FUNCIÓN SQL LOWER
Desde el principio del tutorial queremos obtener los nombres de los
autores escritos correctamente; con la primera letra en mayúsculas y las
demás en minúsculas. Ya hemos conseguido la primera letra en
mayúscula y ahora vamos a conseguir el resto de la palabra en
minúsculas. Para esto utilizamos la siguiente función LOWER();
FUNCIÓN SQL CONCAT
Retorna un string que es el resultado de concatenar dos o más valores
(strings).

SINTAXIS FUNCIÓN SQL CONCAT


CONCAT ( string_value1, string_value2 [, string_valueN ] );
EJEMPLO DE LA FUNCIÓN SQL CONCAT
Siguiendo con el ejemplo queremos unir la primera letra con el resto del
nombre del autor. Para esto utilizaremos la función CONCAT, que unirá la
primera letra en mayúscula de la columna "autor" con el resto de la
palabra en minúscula;
El resultado obtenido es el nombre completo del autor, escrito
correctamente.

----------- ------------- ------------ --------------


--------- -------------- --------------
------------------ ----------- ----------------
Permitir conexiones externas
a MySQL
20 octubre 2015 Sistemas operativos MySQL

Las BBDD de MySQL vienen por defecto con el acceso restringido


desde otro host, por eso es necesario especificarlo en su
configuración para que las aplicaciones que no estén instaladas en
el mismo servidor que el servidor de BBDD puedan conectarse
correctamente.

Hay diversos motivos por los cuales uno no pueda conectarse a


una BBDD de MySQL. Hasta que uno da con la solución puede
ayudarse de un pequeño script realizado en PHP que intente
conectarse y nos muestre el error correspondiente para que
podamos corregirlo. Este script lo tenéis disponible aquí.

Vamos a ver los motivos que pueden estar causando que no


consigamos conectar la aplicación con la BBDD.

La variable SKIP_NETWORKING
Esta variable permite restringir conexiones desde otro servidor. Si
está a ON quiere decir que NO permite atender conexiones
externas. Si estuviera en valor OFF sí permitiría conexiones
externas desde otros hosts.

mysql> SHOW VARIABLES LIKE ‘%netwo%’;


+—————–+——-+
| Variable_name | Value |
+—————–+——-+
| skip_networking | OFF |
+—————–+——-+
1 row in set (0.00 sec)

Para activarla hay que modificar el fichero de configuración

/etc/my.cnf

y reiniciar el servicio de MySQL:


/etc/init.d/mysqld restart.

La variable BIND-ADDRESS
En el fichero de configuración

/etc/init.d/my.cnf

hay que añadir la siguiente lñinea bajo el apartado [mysqld]:

bind-address=0.0.0.0

De esta manera estaremos permitiendo conexiones desde fuera.


Una vez modificado deberemos reiniciar el servicio de MySQL.

-------------------------------------------- ------------------------ -------------------------------------------------

------------------------------------------- --------------------- -----------------------------------------------


-------------------------------------- ------------------------ -------------------------------------------------

------------------------------------------- --------------------- -----------------------------------------

Configurar acceso remoto a MySQL en un


servidor(otra opcion)

Bajo circunstancias normales, los servidores solamente permiten que las


conexiones a MySQL se realicen en forma local, es decir, que las
conexiones se realicen desde el servidor mismo y no desde un server o
equipo externo. Si necesitas correr MySQL en una máquina aparte (para no
sobrecargar el servidor por ejemplo), o si simplemente necesitas conectarte
en forma remota, entonces aquí te mostraremos cómo permitir estas
conexiones.

Primero que nada debemos ingresar a nuestro servidor por medio de SSH.
Una vez estamos dentro (como root), toca darle privilegios de acceso
remoto a la base de datos con la cual trabajaremos. Por ejemplo:

# mysql -u root -p
mysql> update db set Host=’111.11.11.1‘ where db=’nombre_bd‘;
mysql> update user set Host=’111.11.11.1‘ where user=’usuario_bd‘;

Lo que hicimos en la primera sintaxis fue ingresar en la subconsola de


MySQL con privilegios de root de MySQL, para lo cual necesitamos dicha
contraseña por supuesto. En la segunda línea hay que reemplazar
“111.11.11.1” por la IP correspondiente que tendrá acceso. También hay
que reemplazar “nombre_bd” por el nombre de la base de datos en
cuestión. Finalmente, volvemos a indicar la IP y cambiamos “usuario_bd”
por el usuario que hará la conexión.

Como alternativa, en el caso de que quieras acceso remoto para todas las
bases de datos:

mysql> GRANT ALL ON *.* to root@’111.11.11.1‘ IDENTIFIED BY


‘contraseña_de_root‘;

mysql> FLUSH PRIVILEGES;

mysql> exit;

Aquí lo que hacemos es garantizar privilegios sobre todas las bases de datos
al usuario root del servidor remoto. Aunque nunca es conveniente hacerlo,
generalmente es mejor crear un usuario con menos privilegios y que pueda
acceder solo a la base de datos necesaria para la conexión.

Finalmente, lo que hay que hacer es habilitar el puerto 3306 en Iptables.


Una sintaxis sencilla para hacerlo es:

# /sbin/iptables -A INPUT -i eth0 -p tcp –destination-port 3306 -j ACCEPT

Guardamos los cambios:

# service iptables sabe

Ahora ya deberías poder conectarte en forma remota sin problemas.

Mysql – Error Lock wait


timeout exceeded
30 marzo 2015 Bases de Datos MySQL

La variable innodb_lock_wait_timeout indica el tiempo que


va a mantenerse en espera hasta que un resgistro pueda quedar
bloqueado. Pasado ese tiempo, si sigue bloqueado interrumpirá la
tarea que estaba haciendo.

La siguiente instrucción te puede dar una pista de qué produce los


bloqueos. Hay que lanzarlo justamente después de que se
produzca para tener información más certera:

mysql -h localhost -u root -e “show engine innodb status\g” >


/home/user/innodb_status.txt
También podemos comprobar qué valor tenemos actualmente de
la variable que comentábamos:

mysql> show variables like ‘innodb_lock_wait_timeout’;

Por defecto tiene el valor 50, e indica que realiza una espera de
50″ si se produce un bloqueo. Yo conseguí resolver mi problema
ampliando el valor de esa variable a 100.

Para ampliar el valor podemos hacerlo así:

mysql> set innodb_lock_wait_timeout=100

O modificando el tichero /etc/my.cnf poniendo la variable e el


valor justo después de [mysqld]. Como la anterior forma no me
funcionaba, tuve que hacerlo modificando el fichero de
configuración.

Forzar el desbloqueo de tablas en MySQL


Otro método que nos puede ser muy útil para resolver nuestro
problema es mirando el estado de los procesos de MySQL. Con
esto lo que queremos hacer es romper los bloqueos existentes que
estén causados por una SQL.

Para ello vamos a averiguar qué tablas tienen bloqueos y después


vamos a listar los procesos de MySQL que están activos para
después matarlos manualmente.

1) Entramos en MySQL desde consola de comandos:

mysql -u usario -pcontraseña (sin espacio entre -p y la contraseña)

2) Mostramos la tablas que tienen bloqueos:

mysql> show open tables where in_use>0;


3) Mostramos la lista de procesos que están en ejecución, y nos
fijamos en aquel que esté usando la tabla que en el comando
anterior nos apareció como que tenía bloqueos:

mysql> show processlist;

+—-+——+———–+——+———+——+——-+——————+
| Id | User | Host | db | Command | Time | State | Info |
+—-+——+———–+——+———+——+——-+——————+
| 4 | root | localhost | NULL | Query | 0 | NULL | show
processlist |
+—-+——+———–+——+———+——+——-+——————+

Este resultado es un ejemplo para que se vea qué información


mostraría. Si hubiera una tabla con bloqueo, saldría en la lista.

4) Ahora solo queda matar el proceso que produce el bloqueo


indicando el ID del proceso:

mysql> kill id_proceso;

Cuando lo hayamos hecho, si listamos de nuevo los procesos,


aparecerá marcado como killed en la columna Command.

Si el listado de procesos a matar fuera muy grande, se puede


gestionar de la siguiente manera:

 Generamos un TXT con todos los comandos kill por cada uno de
los procesos:

mysql> SELECT concat(‘KILL ‘,id,’;’)


FROM information_schema.processlist
WHERE user=’root’ and INFO like ‘SELECT%’ into outfile
‘/tmp/procesos.txt’;
 Lanzamos todos los comandos kill:

mysql> source /tmp/procesos.txt;

Si vemos que seguimos sin resolver el problema, podemos intentar


en un último caso en reiniciar el MySQL.
--------------------- ----------------------------- --------------------------------------- --------------

--------------- --------------------- ----------------------- -------------------------------- -------------------


-------- ------------------- ------------------------------------------ --------------------------

MySQL – Error The total number of


locks exceeds the lock table size
25 marzo 2015 Bases de Datos MySQL

Este error me ocurrió cuando la aplicación que estaba utilizando


estaba intentando lanzar una SQL que tenía una claúsula IN en el
where con demasiados elementos, y el buffer no tiene capacidad
para tratarlos todos para que nos entendamos. Para ello hay que
ampliar el tamaño de la variable innodb_buffer_pool_size.

ERROR 1206 (HY000): The total number of locks exceeds the lock
table size

Por defecto, la variable innodb_buffer_pool_size viene


configurada con 8Mb. Lo ideal es configurarlo hasta un máximo
del 80% de la memoria de nuestra máquina, y que al menos sea un
60% superior al tamaño de nuestras BBDD. Con esta SQL
podemos saber el tamaño recomendado que necesitaríamos poner:

SELECT
CEILING(Total_InnoDB_Bytes*1.6/POWER(1024,3))
RIBPS
FROM (SELECT SUM(data_length+index_length)
Total_InnoDB_Bytes

FROM information_schema.tables

WHERE engine='InnoDB') A;

pero tenemos que tener en cuenta el no pasarnos del 80% del total
de nuestra memoria.

Para saber qué valor tiene actualmente basta con lanzar el


siguiente comando desde consola:

SHOW VARIABLES LIKE ‘%innodb_buffer_pool_size%’;

Una vez sepamos el valor que queremos asignarle, tenemos que


modificar el fichero/etc/my.cnf, y poner justo debajo de
[mysqld] lo siguiente:

innodb_buffer_pool_size=50M

Si nuestro cambio es para una máquina de desarrollo no es


necesario ponerle mucha cantidad.

Y reiniciarmos el servidor apache:

cd /etc/init.d/mysql start

/etc/init.d/mysql stop

Puede que de error el comando mysql y haya que usar el comando


mysqld. Con cualquiera de los funciona.

--------------------- - ------------------------------ ---------------------------------- ---------------------------


----------------- ----------------------------------------- ------------------------------------- -----
------------------------------------------- --------------------------------- ----------------------------

Relacionar Tablas en Mysql

MySQL Workbench:
Procederemos a abrir la aplicación y nos dirigimos al menú “Database”, y
luego damos clic en “Query Database…”:

Aparecerá una ventana en la cual daremos clic en el botón “OK”:


En la siguiente ventana que nos aparece, observaremos que en la barra
lateral izquierda, se ubicarán todas las Bases de datos que vayamos
creando, ahora ubicaremos la base de datos que creamos con anterioridad
“bdcontactos”, y daremos doble clic sobre la misma:

Como pudimos observar en la imagen anterior, se nos muestran tres


carpetas, pero sólo nos centraremos en la que dice “Tables”,
seguidamente daremos doble clic sobre esta, e inmediatamente se
desplegarán las tablas que hemos creado anteriormente: “tcontacto” y
“testudio_realizado”.

Procederemos a seleccionar la tabla donde irá la llave foránea; es decir,


“testudio_realizado”, damos clic derecho y escogemos la opción “Alter
Table…”:

Saldrá una nueva ventana, nos dirigiremos a la pestaña “Foreign Keys”,


ubicada en la parte inferior de esta, y daremos clic sobre ella:

Veremos un nuevo apartado, y en la columna “Foreign Key Name”


digitaremos el nombre de nuestra llave foránea, en este caso la
llamaremos “tcontacto_testudior”:
Luego, daremos clic en la columna “Referenced Table”, y se desplegará
un menú de opciones, en el cual escogeremos el nombre de la tabla de
donde proviene la llave foránea, en este caso es “tcontacto”:

El siguiente paso a realizar, será activar la casilla del campo que


representa nuestra llave foránea en la tabla sobre la cual nos encontramos
actualmente; es decir, “id_contacto”; seguidamente, en la columna
“Referenced Column” seleccionaremos la columna de la tabla “tcontacto”,
la cual representa la llave primaria de dicha tabla; es decir, “id_contacto”:

Ahora, en el área de “Foreign Key Options”, en las propiedades de “On


Update” y en “On Delete”, dejaremos las opciones que están por defecto;
en este caso “NO ACTION”. Hay que aclarar que esto dependerá de
nuestras necesidades, ya que dejando estas opciones que están por
defecto, lo que hacemos es que si se intenta actualizar la llave foránea en
la tabla de donde proviene; es decir, en donde es llave principal, dicha
acción no se permitirá; igualmente, si intentamos eliminar el registro que
contiene la llave foránea en la tabla de referencia; es decir, donde es llave
principal, no se permitirá eliminar dicho registro; pero siempre y cuando
hayan registros relacionados entre ambas tablas:

Daremos clic en el botón “Apply”, y posteriormente clic en el botón “Apply


SQL” y después en el botón “Finish”, de las ventanas que se nos
muestran:
Por último damos clic en el botón “Close”:

------ --------------------- ----------------------------------- -------------------------------------------


---------------------------------- ------------------- ------------------------------- ----------------
--------

CAmbiar el formato de fecha

Date_Format()

The following script uses the DATE_FORMAT() function to display different


formats. We will use the NOW() function to get the current date/time:

DATE_FORMAT(date,format)
DATE_FORMAT(NOW(),'%b %d %Y %h:%i %p')
DATE_FORMAT(NOW(),'%m-%d-%Y')
DATE_FORMAT(NOW(),'%d %b %y')
DATE_FORMAT(NOW(),'%d %b %Y %T:%f')

The result would look something like this:

Nov 04 2014 11:45 PM


11-04-2014
04 Nov 14
04 Nov 2014 11:45:34:243

Вам также может понравиться