openark kit: utilidades DBA para MySQL

openark kit es una serie de scripts en Python que nos facilitará las tareas de DBA (sobre todo para aquellos que no es nuestro fuerte). Consta de las siguientes aplicaciones:

openark kit

Realizar gráficas con MySQL y Google Graph

Buen ejemplo para obtener la URL que nos dibuja gráficas usando Google Graph mediante procedimientos almacenados de MySQL. Está sacado de este ejemplo, que a su vez está sacado de este otro para Oracle.

DELIMITER $$
DROP FUNCTION IF EXISTS `dm_midas`.`FNC_GOOGRAPH_DB_SIZE`$$
CREATE FUNCTION `dm_midas`.`FNC_GOOGRAPH_DB_SIZE` (
p_chart_type CHAR,
p_height INT,
p_width INT) RETURNS varchar(3000) CHARSET latin1
READS SQL DATA
BEGIN
/* Author:    Walter Heck - OlinData */
/* Date:      20090216 */
/* Note:      After an idea by Alex Gorbachev - Pythian */
/*            http://www.pythian.com/blogs/1490/google-charts-for-dba-tablespaces-allocation */
/* variable declaration */
DECLARE v_done BOOLEAN default false;
DECLARE v_url varchar(3000);
DECLARE v_schema_name varchar(3000);
DECLARE v_data_length_sum int;
DECLARE v_data_length_total int;
DECLARE v_legend_labels varchar(3000);
DECLARE v_chart_labels varchar(3000);
DECLARE v_chart_data varchar(3000);
/* Cursor declaration */
DECLARE c_schema_sizes cursor for
select
t.table_schema,
round(sum(t.data_length + t.index_length) / 1024 / 1024) as data_length_schema
from
information_schema.tables t
group by
t.table_schema
order by
t.table_schema;
/* Handler declaration */
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = true;
/* Initialize the variables */
SET v_legend_labels = '';
SET v_chart_labels = '';
SET v_chart_data = '';
/* Get the total data length + index_length for all tables */
select
round(sum(t.data_length + t.index_length) / 1024 / 1024) as data_length_total
into
v_data_length_total
from
information_schema.tables t;
/* Open the cursor */
OPEN c_schema_sizes;
/* Loop through the cursor */
get_data: LOOP
/* Fetch the next row of data into our variables */
FETCH c_schema_sizes INTO v_schema_name, v_data_length_sum;
/* if there is no more data, v_done will be true */
IF v_done THEN
/* Exit the loop */
LEAVE get_data;
END IF;
/* Add the schema name to the labels for the legend */
IF v_legend_labels = '' THEN
SET v_legend_labels = v_schema_name;
ELSE
SET v_legend_labels = concat(v_legend_labels, '|', v_schema_name);
END IF;
/* Add the total size of the schema to the labels */
IF v_chart_labels = '' THEN
SET v_chart_labels = v_data_length_sum;
ELSE
SET v_chart_labels = concat(v_chart_labels, '|', v_data_length_sum);
END IF;
/* Get the percentage of the total size as the graph's data */
IF v_chart_data = '' THEN
SET v_chart_data = ROUND(v_data_length_sum / v_data_length_total, 2) * 100;
ELSE
SET v_chart_data = concat(v_chart_data, ',', ROUND(v_data_length_sum / v_data_length_total, 2) * 100);
END IF;
END LOOP get_data;
/* Close the cursor */
CLOSE c_schema_sizes;
/* Build up the google graph url */
SET v_url = 'http://chart.apis.google.com/chart?';
SET v_url = CONCAT(v_url, 'cht=', p_chart_type);
SET v_url = CONCAT(v_url, '&chs=', p_width , 'x', p_height);
SET v_url = CONCAT(v_url, '&chtt=Database Sizes (MB)');
SET v_url = CONCAT(v_url, '&chl=', v_chart_labels);
SET v_url = CONCAT(v_url, '&chd=t:', v_chart_data);
SET v_url = CONCAT(v_url, '&chdl=', v_legend_labels);
/* return the url as the function's result */
RETURN v_url;
END$$
DELIMITER ; 

MySQL DB Pie Graph

Intercambiando el valor de columnas en MYSQL

Interesantes métodos para intercambiar el valor de dos columnas en MySQL.

UPDATE swap_test SET x=y, y=@temp WHERE (@temp:=x) IS NOT NULL;

Este método no funciona cuando alguna de las columnas tiene valor NULL, y los paréntesis son obligatorios.

Otro método, que no tendría problemas con los NULL, sería:

UPDATE swaptest s1, swaptest s2 SET s1.x=s1.y, s1.y=s2.x WHERE s1.id=s2.id;

Swapping Column Values in MySQL

Seleccionar cercanos mediante MySQL

En algunos casos tenemos la necesidad de buscar registros cercanos a un cierto valor (numérico, logicamente). Una solución sencilla es obtener el valor absoluto de la resta entre el valor que buscamos y el valor del registro, ordenar por ese valor y limitar la búsqueda a n registros:

SELECT number, ABS( number - 2500 ) AS distance
FROM numbers
ORDER BY distance
LIMIT 6

El problema es que esta consulta es lenta, y en producción no nos podemos permitir consultas lentas, por lo que una opción mucho más eficiente es en vez de realizar esa consulta sobre todos los registros, realizarla sobre la unión de dos consultas: una de los n/2 registros con valor superior al que buscamos y otra con los n/2 registros con valor menor al que buscamos, y luego ordenando como la consulta anterior y cogiendo solo los elementos que nos interesan:

SELECT number, ABS( number - 2500 ) AS distance FROM (
(
SELECT number
FROM `numbers`
WHERE number >=2500
ORDER BY number
LIMIT 6
) UNION ALL (
SELECT number
FROM `numbers`
WHERE number <2500
ORDER BY number DESC
LIMIT 6
)
) AS n
ORDER BY distance
LIMIT 6

Selecting closest values in MySQL

Vía / dzone

Obtener logs de todas las queries con MySQL 5.0

En algunas ocasiones necesitamos tener un log de todas las queries que se realizan, sobre todo en preproducción para poder tener una visión general de qué consultas se realizan y del coste.
En MySQL 5.1 es sencillo porque se puede poner el tiempo máximo para slow queries a milisegundos, por lo que todas las queries serían lentas y obtendríamos datos de sobre las consultas bastante interesantes.
En MySQL 5.0 tan solo se puede reducir el tiempo de slow queries a un segundo, por lo que es necesario usar tcpdump para capturar el tráfico de MySQL a un log y luego mediante otros comandos obtener las queries.
Logging all the queries with MySQL 5.0

Autosugerencias usando MySQL índices fulltext

Interesante seríe de tres artículos que nos muestra como crear un autosuggest tipo Google usando los índices full-text de MySQL. El método no es nada sencillo (php, mysql y listo), por lo que no será fácil probarlo, pero tampoco complicado o imposible (se necesita ser un usuario algo más avanzado).
Se trata de coger el fichero del índice full-text y usando un programa C, que es necesario compilar junto a MySQL, accederá a los términos que cumplan el texto base del auto-suggest y lo devolverá.
Como ya he comentado se trata de una aplicación externa, por lo que su integración con nuestra aplicación web deberá ejecutarla como proceso externo.
Implementing an AutoSuggest feature using MySQL fulltext indices

Curiosidades sobre TIMESTAMP en MySQL

Interesante lo que descubre uno sobre el TIMESTAMP en MySQL:

  • Por defecto TIMESTAMP es NOT NULL, insertar un NULL hace que se almacene el DATETIME actual
  • TIMESTAMP puede tener un valor entre ‘1970-01-01 00:00:01′ y ‘2038-01-19 03:14:07′
  • Solo la primera columna con NOT NULL puede tener por defecto la propiedad CURRENT_TIMESTAMP
  • Cuando CURRENT_TIMESTAMP se indica como ON UPDATE esa columna no se actualiza si no hay cambios significativos (por ejemplo al hacer dos updates iguales)

Interesting things about TIMESTAMP data type in MySQL

Alternativa a MySQL Query Analyzer

MySQL ha lanzado su nueva versión de MySQL Query Analyzer dentro de MySQL Enterprise, de la cual hablan muy bien en casi todos los blogs. Para aquellos que usemos la versión Community, podemos usar una alternativa gratuita a esa herramienta.
Para ello debemos instalar los parches que ofrece Percona los cuales, entre otras cosas, permiten obtener métricas desde el propio servidor. También habrá que utilizar mysqlsla que parsea, filtra, analiza y ordena los logs de MySQL para crear informes personalizados de las queries y sus meta-propiedades.
An alternative to the MySQL Query Analyzer

Social Web: clon de Digg, Meneame o Reddit en PHP y MySQL

Social Web CMS es un sistema de noticias social al estilo de Digg o Menéame que está desarrollado en PHP y MySQL y que nos permite crear nuestro clon de forma sencilla.
Permite la inserción de artículos por parte de los usuarios, votar los artículos, realizar comentarios, valorar los comentarios, buscar contenidos, obtener feeds para secciones, categorías y usuarios, disponer de perfiles, mensajes privados … Además dispone de una administración que permite gestionar el anti-spam, bloquear URLs, importar RSS, …
Social Web CMS

SQL injection cheatsheet

Interesante hoja de trucos para evitar SQL Injection en nuestras aplicaciones. La explicación es bastante intensa y no solo se centra en MySQL sino en otros motores como Microsoft SQL Server, ORACLE y PostgreSQL, aunque para estos últimas son pocos los consejos.
SQL Injection Cheat Sheet