mysql
Noticias
Unidades para cambiar valores de MySQL en calienteMediante SET GLOBAL / SET SESSION podemos modificar ciertos valores de MySQL, pero no aceptan unidades: mysql> set session max_allowed_packet=20M; ERROR 1232 (42000): Incorrect argument type to variable 'max_allowed_packet' En lugar de tener que calcularlo fuera del MySQL, podemos indicar la operación. Por ejemplo, para 20M podemos indicar 20*102*1024: mysql> show variables like 'max_allowed_packet'; +--------------------+----------+ | Variable_name | Value | +--------------------+----------+ | max_allowed_packet | 10485760 | +--------------------+----------+ 1 row in set (0.00 sec) mysql> set session max_allowed_packet=20*1024*1024; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'max_allowed_packet'; +--------------------+----------+ | Variable_name | Value | +--------------------+----------+ | max_allowed_packet | 20971520 | +--------------------+----------+ 1 row in set (0.00 sec) mysql> Tags: MySQL Relacionados Vistas (views) en MySQL Ver los storage engines disponibles en MySQL Ver el usuario con el que estamos conectados en Oracle y MySQL Ver el estado de un MySQL Uso de mk-find para realizar analyze y optimize de las tablas MySQL
planetmysql.org | 14-may-2012 09:22
SHUTDOWN vs SIGTERM en un MySQL
Existe la creencia que mandar un SIGTERM a un mysqld no es la forma correcta de apagar un MySQL, en realidad es otra opción igual de válida. En la documentación de MySQL referente al apagado del daemon podemos ver los pasos que se realizan: Ya sea mediante el mysqladmin shutdown o cuando el mysqld recibe un SIGTERM se inicia el proceso de apagado Si es un cliente que manda el shutdown (mysqldadmin shutdown) se crea un thread para gestionar el apagado del daemon. Si se manda el thread se puede crear o ser gestionado directamente por el handler del evento A continuación deja de aceptar nuevas conexiones Se matan todas las conexiones establecidas mantado las queries y haciendo rollback de las transacciones Finalmente pasa a disco todos los buffers necesarios para cada storage engine y finaliza el proceso A diferencia de Oracle, no dispone de otros modos de apagado. Haciendo la equivalencia sería como un SHUTDOWN IMMEDIATE Tags: MySQL Relacionados Vistas (views) en MySQL Ver los storage engines disponibles en MySQL Ver el usuario con el que estamos conectados en Oracle y MySQL Ver el estado de un MySQL Uso de mk-find para realizar analyze y optimize de las tablas MySQL
planetmysql.org | 10-may-2012 09:26
Exportación de bases de datos con mysqldump
Al exportar una base de datos con mysqldump y quererla reimportar deberemos vigilar si nos añade el use database por si queremos importarla con otro nombre. Las opciones de mysqldump al respecto son: $ mysqldump Usage: mysqldump [OPTIONS] database [tables] OR mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...] OR mysqldump [OPTIONS] --all-databases [OPTIONS] For more options, use mysqldump --help Para exportar una base de datos, podemos usar indistintamente mysqldump o mysqldump –databases , pero existe una pequeña diferencia: Con la opción –databases podemos indicar más de una única base de datos, por lo que nos añadirá el comando use db antes de exportar cada base de datos. Por lo tanto, si luego queremos importar el dump en otra base de datos deberemos eliminar el comando del fichero o ejecutar el mysqldump sin la opción –databases que no añade el comando. Tags: MySQL Relacionados Vistas (views) en MySQL Ver los storage engines disponibles en MySQL Ver el usuario con el que estamos conectados en Oracle y MySQL Ver el estado de un MySQL Uso de mk-find para realizar analyze y optimize de las tablas MySQL
planetmysql.org | 08-may-2012 10:14
analyze y optimize en MySQL slaves
En un MySQL con replicación, todo lo que acaba en el binlog se consideran modificaciones que se traspasan a los slaves para que sean modificados igual que el master. En el caso de los analyze y optimize, no se ve tan claro como un update: analyze: Actualiza la información que utiliza el optimizador sobre la distribución de las filas en la tabla optimize: Elimina el espacio que ya no se usa: Cuando un dato es eliminado es marcado como eliminado en lugar de eliminar-se, con este comando recreamos la tabla eliminando el espacio no utilizado Estos comandos acaban en el binlog, por lo que no hace falta tener estas tareas programadas en los slaves. Mediante el comando mysqlbinlog lo podemos ver: $ mysqlbinlog mysql-bin.000001 /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; # at 4 #120426 9:55:16 server id 1 end_log_pos 106 Start: binlog v 4, server v 5.1.30-debug-log created 120426 9:55:16 at startup # Warning: this binlog was not closed properly. Most probably mysqld crashed writing it. ROLLBACK/*!*/; # at 106 #120426 9:55:50 server id 1 end_log_pos 189 Query thread_id=1 exec_time=0 error_code=0 SET TIMESTAMP=1335426950/*!*/; SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1/*!*/; SET @@session.sql_mode=0/*!*/; /*!\C latin1 *//*!*/; SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; create database test /*!*/; # at 189 #120426 9:56:04 server id 1 end_log_pos 277 Query thread_id=1 exec_time=0 error_code=0 use test/*!*/; SET TIMESTAMP=1335426964/*!*/; create table test(id int) /*!*/; # at 277 #120426 9:56:07 server id 1 end_log_pos 358 Query thread_id=1 exec_time=0 error_code=0 SET TIMESTAMP=1335426967/*!*/; analyze table test /*!*/; # at 358 #120426 9:56:14 server id 1 end_log_pos 440 Query thread_id=1 exec_time=0 error_code=0 SET TIMESTAMP=1335426974/*!*/; optimize table test /*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; Tags: MySQL Relacionados Vistas (views) en MySQL Ver los storage engines disponibles en MySQL Ver el usuario con el que estamos conectados en Oracle y MySQL Ver el estado de un MySQL Uso de mk-find para realizar analyze y optimize de las tablas MySQL
planetmysql.org | 27-abr-2012 07:10
Timeouts de MySQL: wait_timeout vs interactive_timeout
En MySQL existen dos timeouts diferentes según si el cliente se identifica como una conexión interactiva o no. Las variables que definen estos timeouts son wait_timeout y interactive_timeout Si definimos en el my.cnf los siguientes timeouts: wait_timeout=60 interactive_timeout=90 Con el siguiente código PHP: Obtendremos el valor de wait_timeout de la sessión no interactiva: $ php wait.php Array ( [Variable_name] => wait_timeout [Value] => 60 ) Pero si nos conectamos con el cliente de consola el valor de wait_timeout tomará el valor de interactive_timeout: mysql> show variables like 'wait%'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | wait_timeout | 90 | +---------------+-------+ 1 row in set (0.00 sec) Es responsabilidad del cliente identificarse, por lo que para obtener el wait_timeout de una sesión interactiva únicamente deberemos añadir el flag MYSQL_CLIENT_INTERACTIVE al conectarnos: $link = mysql_connect('localhost', 'root', '', 0, MYSQL_CLIENT_INTERACTIVE); Y ya tendremos el timeout de la sesión interactiva: $ php wait.php Array ( [Variable_name] => wait_timeout [Value] => 90 ) Tags: MySQL Relacionados Vistas (views) en MySQL Ver los storage engines disponibles en MySQL Ver el usuario con el que estamos conectados en Oracle y MySQL Ver el estado de un MySQL Uso de mk-find para realizar analyze y optimize de las tablas MySQL
planetmysql.org | 23-abr-2012 10:01
Unknown table engine InnoDB
El error “Unknown table engine InnoDB” puede ser que tengamos el engine deshabilitado en el my.cnf con skip-innodb pero también puede ser que nos enfrentemos a problemas de memoria: En el caso que en el my.cnf no tengamos el skip-innodb, deberemos comprobar el log del MySQL ya que nos podemos encontrar con: 120413 19:40:18 InnoDB: Error: cannot allocate 157302784 bytes of InnoDB: memory with malloc! Total allocated memory InnoDB: by InnoDB 7994352 bytes. Operating system errno: 12 InnoDB: Check if you should increase the swap file or InnoDB: ulimits of your operating system. InnoDB: On FreeBSD check you have compiled the OS with InnoDB: a big enough maximum process size. InnoDB: Note that in most 32-bit computers the process InnoDB: memory space is limited to 2 GB or 4 GB. InnoDB: We keep retrying the allocation for 60 seconds... InnoDB: Fatal error: cannot allocate the memory for the buffer pool 120413 19:41:18 [ERROR] Plugin 'InnoDB' init function returned error. 120413 19:41:18 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed. Nos indica que no ha podido cargar el engine en memoria, por lo que queda deshabilitado. Deberemos comprobar tanto los parámetros del MySQL que sean correctos como en el equipo si existe suficiente memoria para el MySQL. Tags: MySQL Relacionados Vistas (views) en MySQL Ver los storage engines disponibles en MySQL Ver el usuario con el que estamos conectados en Oracle y MySQL Ver el estado de un MySQL Uso de mk-find para realizar analyze y optimize de las tablas MySQL
planetmysql.org | 20-abr-2012 08:56
Migrando un MySQL de cabina usando un master-slave
Toda migración acaba obteniendo una cierta complejidad si queremos minimizar el tiempo de corte y poder garantizar haya una “vuelta atrás” en caso de problemas. Vamos a ver una forma de migrar un MySQL master de un disco de una cabina a otro disco de otra cabina minimizando el tiempo de corte gracias a un slave que transformamos en master y volvemos a transformar en slave. Suponiendo que tenemos un MySQL con un slave y queremos migrar de un disco en una cabina antigua a otro disco de una cabina nueva: Mientras se traspasan los datos podemos usar el slave como master y cuando acabe podemos sincronizar los dos MySQL y volver a dejar el MySQL con su rol habitual. La hora de ruta sería la siguiente: Previo a la intervención: Apagar procesos batch (crons): Pasaremos de dos MySQL a uno solo, por lo que deberemos dejar únicamente los procesos esenciales Primera fase: Apagamos la web y todos los procesos: De esta forma garantizamos que no se produzcan modificaciones mientras estamos realizando la intervención En el slave, mediante SHOW SLAVE STATUS comprobamos que Seconds_Behind_Master esta a cero En el master, mediante SHOW MASTER STATUS comprobamos que no se produzcan modificaciones Apagamos el MySQL master Apagamos el MySQL slave En el slave, borramos la configuración especifica de slave y lo dejamos como un master conservando el mismo server-id En el slave, borramos del datadir los ficheros: master.info relay-log.info mysqld-relay-bin.* Arrancamos el antiguo slave. Si hacemos un SHOW MASTER STATUS veremos que empieza: SLAVE ( (none) ) > show master status; +---------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +---------------+----------+--------------+------------------+ | binlog.000001 | 106 | | | +---------------+----------+--------------+------------------+ 1 row in set (0.00 sec) Arancamos la web apuntando al antiguo slave y los demás procesos ensenciales Con esto conseguimos con un corte aproximado de 5 minutos cambiar el slave a master. A continuación podremos proceder a intervenir en el antiguo MySQL master para copiar el datadir entre las cabinas: Primero deberemos asegurarnos que el MySQL no arranca al inicio del sistema por si debemos reinciar el equipo, por ejemplo, para añadir alguna interfaz A continuación deberemos copiar los datos entre los dos discos Arrancamos el antiguo master con el datadir nuevo como slave, modificando la configuración de MySQL y dejándolo en sólo lectura para evitar escrituras fortuitas En el antiguo slave, nuevo master, deberemos añadir un usuario para que se replique: GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%' IDENTIFIED BY 'secretitosdevieja'; En el antiguo master deberemos decir que replique los datos desde el nuevo master desde el principio: CHANGE MASTER TO MASTER_HOST='slaveoriginal', MASTER_USER='slave', MASTER_PASSWORD='secretitosdevieja', MASTER_LOG_FILE='binlog.000001', MASTER_LOG_POS=106; A continuación deberemos esperar hasta que en el antiguo master el SHOW SLAVE STATUS nos muestre que ya ha acabado de sincronizar (Seconds_Behind_Master esta a cero) En el antiguo master, deberemos volver a habilitar el MySQL para que arranque con el sistema Finalmente deberemos volver a dejar los MySQL en su rol habitual: Apagamos la web y todos sus procesos En el antiguo master, mediante SHOW SLAVE STATUS comprobamos que Seconds_Behind_Master esta a cero En el antiguo slave, mediante SHOW MASTER STATUS comprobamos que no se produzcan modificaciones Apagamos ambos MySQL Volvemos a dejar la configuración del master como estaba en el inicio Borramos del datadir los ficheros: master.info relay-log.info mysqld-relay-bin.* Arrancamos el master original, si hacemos un SHOW MASTER STATUS veremos que empieza de nuevo desde el inico: MASTER ( (none) ) > show master status; +---------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +---------------+----------+--------------+------------------+ | binlog.000001 | 106 | | | +---------------+----------+--------------+------------------+ 1 row in set (0.00 sec) Cambiamos la configuración del slave En el slave borramos los binlogs que se han generado mientras actuaba como master: binlog.* Arrancamos el slave Indicamos que vuelva a sincronizar desde el master: CHANGE MASTER TO MASTER_HOST='masteroriginal', MASTER_USER='slave', MASTER_PASSWORD='secretitosdevieja', MASTER_LOG_FILE='binlog.000001', MASTER_LOG_POS=106; Arrancamos la web con la configuración original y demás procesos Con este movimiento master a slave, sincronizar desde el viejo master al antiguo slave y volver a girar el master por el slave conseguimos una migración con poco tiempo de corte y conservando los datos originales por si surge algún imprevisto. Tags: MySQL Relacionados Vistas (views) en MySQL Ver los storage engines disponibles en MySQL Ver el usuario con el que estamos conectados en Oracle y MySQL Ver el estado de un MySQL Uso de mk-find para realizar analyze y optimize de las tablas MySQL
planetmysql.org | 18-abr-2012 07:26
Posts publicados en MySQL High Performance
Como ya comenté anteriormente ahora mis esfuerzos de blogging se centran más en generar contenido para MySQL High Performance :) Para los que quieran un rápido listado de mis últimos posts, aquí lo tenéis: Avoiding auto-increment holes on InnoDB with INSERT IGNORE Statement based replication with Stored Functions, Triggers and Events Actively monitoring replication connectivity with MySQL’s heartbeat How to recover a single InnoDB table from a Full Backup How to recover deleted rows from an InnoDB Tablespace InnoDB’s gap locks Y si, prometo volver a escribir en mi blog en un futuro cercano. Solo necesito reordenar mi vida :)
planetmysql.org | 01-abr-2012 10:52
Ver los storage engines disponibles en MySQL
Un MySQL puede estar compilado para soportar varios STORAGE ENGINES, vamos a ver de los que disponemos y sus características: El comando para ver el tipo de tablas que podemos usar en el MySQL es con SHOW STORAGE ENGINES o SHOW ENGINES: mysql> show engines; +------------+---------+----------------------------------------------------------------+--------------+------+------------+ | Engine | Support | Comment | Transactions | XA | Savepoints | +------------+---------+----------------------------------------------------------------+--------------+------+------------+ | ndbcluster | YES | Clustered, fault-tolerant tables | YES | NO | NO | | MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO | | ndbinfo | YES | MySQL Cluster system information storage engine | NO | NO | NO | | CSV | YES | CSV storage engine | NO | NO | NO | | MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO | | FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL | | ARCHIVE | YES | Archive storage engine | NO | NO | NO | | InnoDB | YES | Supports transactions, row-level locking, and foreign keys | YES | YES | YES | | MyISAM | DEFAULT | Default engine as of MySQL 3.23 with great performance | NO | NO | NO | | BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO | +------------+---------+----------------------------------------------------------------+--------------+------+------------+ 10 rows in set (0.08 sec) Además de mostrarnos el nombre y si esta o no disponible, nos muestra una descripción y si soporta o no las siguientes características: Transacciones: Soporte de transacciones, InnoDB y NDB son los únicos storage engines que vienen con el propio MySQL que las soportan Savepoints: Puntos intermedios de las transacciones, para volver a un punto sin cancelar la transacción completamente Transacciones XA: Soporte de transacciones globales entre diferentes partes (procesos) que intervienen en la transacción Tags: MySQL Relacionados Vistas (views) en MySQL Ver el usuario con el que estamos conectados en Oracle y MySQL Ver el estado de un MySQL Uso de mk-find para realizar analyze y optimize de las tablas MySQL Uso de Maatkit para detectar índices duplicados en MySQL
planetmysql.org | 27-mar-2012 09:42
Migrar de MS Access a MySQL con relaciones
He usado herramientas como MySQL Migration Toolkit (*) y Bullzip’s Access To MySQL, ambos hacen un excelente trabajo pero no exporta las relaciones entre tablas. Hacer esta tarea nos puede tomar varias horas (hasta ahora): Escribí un código VBA para identificar las relaciones generando código MySQL con las sentencias de creación, esto puede ser muy útil después de la migración usando cualquier herramienta libre. Option Explicit 'Copiar y pegar esta función en un módulo nuevo/existente de MS Access. Public Sub printRelations() Dim sql, fk As String Dim i, j As Integer For i = 0 To CurrentDb.Relations.Count - 1 sql = "ALTER TABLE `" & CurrentDb.Relations(i).ForeignTable & _ "` ADD CONSTRAINT `" & CurrentDb.Relations(i).Name & "` FOREIGN KEY (" fk = "(" For j = 0 To CurrentDb.Relations(i).Fields.Count - 1 sql = sql & "`" & CurrentDb.Relations(i).Fields(j).ForeignName & "` ," fk = fk & "`" & CurrentDb.Relations(i).Fields(j).Name & "` ," Next j sql = Left(sql, Len(sql) - 1) fk = Left(fk, Len(fk) - 1) fk = fk & ")" sql = sql & ") REFERENCES `" & CurrentDb.Relations(i).Table & "`" & fk & ";" Debug.Print sql Next i End Sub Para ejecutar el código anterior, debemos invocarlo desde la ventana de Inmediato (Ctrl+G), luego solo tendremos que copiar el SQL generado para llevarlo a MySQL. Enjoy! (*)MySQL Migration Toolkit esta descontinuado pero aun sigue disponible desde los servidores Mirror de MysQL como: http://mirrors.dotsrc.org/mysql/Downloads/MySQLGUITools/
planetmysql.org | 17-mar-2012 04:09
Mantener varios snapshots de MySQL online
En ciertas bases de datos dónde el tiempo de recuperación de una tabla es crítico podemos mantener un conjunto de snapshots online (penalizando el rendimiento del disco) con el fin de disponer de puntos de recuperación muy cercanos al estado actual. Vamos a ver como configurarlo usando mylvmbackup Primero lo descargamos: cd /usr/local/src wget http://www.lenzg.net/mylvmbackup/mylvmbackup-0.13.tar.gz tar xzf mylvmbackup-0.13.tar.gz E instalamos normalmente: cd mylvmbackup-0.13 make prefix=/usr/local/ install A continuación deberemos indicar en el fichero de configuración (/etc/mylvmbackup.conf) los datos para acceder al MySQL: [mysql] user=root password=passwdroot host=localhost port=3306 socket=/tmp/mysql.sock mycnf=/etc/my.cnf En la secciones siguientes definimos el LVM que contiene el datadir del MySQL y definimos el resto de datos: # # LVM-specific options # [lvm] vgname=local lvname=mysql backuplv=snap.backup lvsize=5G # # File system specific options # [fs] xfs=0 mountdir=/var/tmp/mylvmbackup/mnt/ backupdir=/var/tmp/mylvmbackup/backup/ relpath= # # Names of required external utilities # Make sure the $PATH is set accordingly, especially for cron jobs! # [tools] lvcreate=/sbin/lvcreate lvremove=/sbin/lvremove lvs=/sbin/lvs mount=/bin/mount tar=/bin/tar compress=/bin/gzip # alternative tar backup compression tools #compress=lzma #compress=bzip2 # or (for no compression): #compress=cat # rsync=rsync rsnap=rsnap umount=/bin/umount La parte importante que debemos configurar se encuentra en la sección misc, dónde le indicaramos que no queremos que haga backup (backuptype=none) y que conserve el snapshot (keep_snapshot=1): # # Other configuration options # [misc] backuptype=none prefix=backup suffix=_mysql tararg=cvf tarsuffixarg= tarfilesuffix=.tar.gz compressarg=--stdout --verbose --best # for LZMA: #compressarg=--stdout --verbose -7 # for bzip2: #compressarg=--stdout --verbose -7 # for cat: #compressarg= # ie. nothing rsyncarg=-avWP rsnaparg=7 datefmt=%Y%m%d_%H%M%S innodb_recover=0 pidfile=/var/tmp/mylvmbackup_recoverserver.pid skip_flush_tables=0 extra_flush_tables=0 skip_mycnf=0 hooksdir=/usr/share/mylvmbackup skip_hooks=0 keep_snapshot=1 keep_mount=0 quiet=0 # # Logging options. The Sys::Syslog module is required for syslog option # See "perldoc Sys::Syslog" for more information. # [logging] # 'console' (STDOUT, STDERR) or 'syslog' or 'both'. log_method=console # 'native', 'tcp', 'udp'. Default is 'native' syslog_socktype=native syslog_facility= # If using remote syslog, don't forget to change the socket type to tcp or udp. syslog_remotehost= A continuación deberemos definir un script que periódicamente lance el mylvmbackup para ir conservando los snapshots: #!/bin/bash mkdir -p /var/spool/bacula mkdir -p /var/tmp/mylvmbackup/backup mkdir -p /var/tmp/mylvmbackup/mnt CURRENTSNAP=$(/bin/date +"%H") /bin/touch /tmp/snap.in.progress /bin/unlink /dev/backup.snap /sbin/lvremove -f /dev/local/snap.${CURRENTSNAP} if [ -n "$(echo "show processlist;" | mysql -uroot -p$(cat /var/mysql/.mysql.root.pass) | grep -i optimize)" ]; then #echo "snapshot $(hostname) anulado" | mail -s "$(hostname) snapshow anulado" MAIL@ejemplo.com exit 0 fi /usr/local/bin/mylvmbackup 2>&1 >/dev/null /sbin/lvrename /dev/local/snap.backup /dev/local/snap.${CURRENTSNAP} /bin/ln -s /dev/local/snap.${CURRENTSNAP} /dev/backup.snap /bin/rm -f /tmp/snap.in.progress Simplemente deberemos definir dicho script en el cron, por ejemplo cada 8 horas: # snaps cada 8 horas 03 */8 * * * /usr/local/bin/mksnap.sh >/dev/null 2>&1 De esta forma tendremos snapshots del datadir disponibles por si tenemos que restaurar algún dato: # lvdisplay | grep "LV Name" | grep snap LV Name /dev/local/snap.16 LV Name /dev/local/snap.00 LV Name /dev/local/snap.08 Y el link /dev/backup.snap siempre apuntará al último snapshot para poder usar-lo en scripts fácilmente. # ls -la /dev/backup.snap lrwxrwxrwx. 1 root root 18 Mar 12 08:03 /dev/backup.snap -> /dev/local/snap.08 Tags: mylvmbackup, MySQL Relacionados Vistas (views) en MySQL Ver el usuario con el que estamos conectados en Oracle y MySQL Ver el estado de un MySQL Uso de mk-find para realizar analyze y optimize de las tablas MySQL Uso de Maatkit para detectar índices duplicados en MySQL
planetmysql.org | 12-mar-2012 09:39
MySQL necesita mejorar sus mensajes de error
Acabo de modificar una base de datos, no debió demorar las dos horas que demoré en realizar la tarea si no fuera por que MySQL no ha mejorado aun sus mensajes de error. La tarea fue agregar una nueva clave foránea a una tabla existente, veamos como reproducir lo que me ha pasado: -- Crear las tablas foo y bar CREATE TABLE foo ( id INTEGER NOT NULL PRIMARY KEY, bar_id INT NOT NULL ); CREATE TABLE bar ( id INTEGER NOT NULL PRIMARY KEY ); -- Intentar crear una clave foránea ALTER TABLE foo ADD FOREIGN KEY(bar_id) REFERENCES bar(ANY_FIELD) ; Al ejecutar la ultima sentencia MySQL devuelve un error genérico que puede significar muchas cosas: Error Code: 1005. Can't create table 'temp.#sql-4bd7_11' (errno: 150) Todo hubiera sido mas fácil si me hubiera dado cuenta que escribí mal el campo de la tabla de deferencia bar(ANY_FIELD) (algunas veces pasa), si el mensaje de horror hubiera dicho: "field bar.ANY_FIELD don't exists" no estaría despierto hasta las 2am buscando una solución, Estoy usando MySQL 5.5.21 community edition.
planetmysql.org | 12-mar-2012 08:00
Que hay en MySQL Enterprise?
Muchos nos hemos hecho esa pregunta, Pedro Andrade y Manuel Contreras de Oracle nos aclaran el asunto, aqui los livestreams grabados del ultimo evento Joomla en Guatemala. Watch live streaming video from desdeguate at livestream.com Watch live streaming video from desdeguate at livestream.com
planetmysql.org | 06-mar-2012 08:22
Valores auto_increment personalizados
En el Perú los formatos numéricos de las facturas es 001-000033 , la serie (001) cambia eventualmente pero el valor auto-incrementado es el mismo: 001-000034 001-000035 001-000036 ... Para manejar esto en MySQL he preparado una solución basada en otro articulo mio: Crear la tabla para guardar los números actuales: CREATE TABLE _sequence ( seq_name VARCHAR(50) NOT NULL PRIMARY KEY, seq_group VARCHAR(10) NOT NULL, seq_val INT UNSIGNED NOT NULL ); Crear una función para obtener el valor siguiente e incrementarlo: delimiter // DROP FUNCTION IF EXISTS getNextCustomSeq// CREATE FUNCTION getNextCustomSeq ( sSeqName VARCHAR(50), sSeqGroup VARCHAR(10) ) RETURNS VARCHAR(20) BEGIN DECLARE nLast_val INT; SET nLast_val = (SELECT seq_val FROM _sequence WHERE seq_name = sSeqName AND seq_group = sSeqGroup); IF nLast_val IS NULL THEN SET nLast_val = 1; INSERT INTO _sequence (seq_name,seq_group,seq_val) VALUES (sSeqName,sSeqGroup,nLast_Val); ELSE SET nLast_val = nLast_val + 1; UPDATE _sequence SET seq_val = nLast_val WHERE seq_name = sSeqName AND seq_group = sSeqGroup; END IF; SET @ret = (SELECT concat(sSeqGroup,'-',lpad(nLast_val,6,'0'))); RETURN @ret; END// delimiter ; Crear un procedimiento almacenado para modificar el valor actual: delimiter // DROP PROCEDURE IF EXISTS sp_setSeqCustomVal// CREATE PROCEDURE sp_setCustomVal(sSeqName VARCHAR(50), sSeqGroup VARCHAR(10), nVal INT UNSIGNED) BEGIN IF (SELECT COUNT(*) FROM _sequence WHERE seq_name = sSeqName AND seq_group = sSeqGroup) = 0 THEN INSERT INTO _sequence (seq_name,seq_group,seq_val) VALUES (sSeqName,sSeqGroup,nVal); ELSE UPDATE _sequence SET seq_val = nVal WHERE seq_name = sSeqName AND seq_group = sSeqGroup; END IF; END// delimiter ; Haciendo algunas pruebas: Crear una tabla: CREATE TABLE custom_autonums ( id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, seq_1 VARCHAR(20), -- custom sequence 1 seq_2 VARCHAR(20), -- custom sequence 2 UNIQUE(seq_1), UNIQUE(seq_2) ); Crear un trigger para la tabla: delimiter // DROP TRIGGER IF EXISTS custom_autonums_bi// CREATE TRIGGER custom_autonums_bi BEFORE INSERT ON custom_autonums FOR each ROW BEGIN SET NEW.seq_1 = getNextCustomSeq("seq_1","001"); SET NEW.seq_2 = getNextCustomSeq("seq_2","DBA"); END// delimiter ; Insertando algunos valores: INSERT INTO custom_autonums (id) VALUES (NULL),(NULL),(NULL); SELECT * FROM custom_autonums; +----+------------+------------+ | id | seq_1 | seq_2 | +----+------------+------------+ | 4 | 001-000001 | DBA-000001 | | 5 | 001-000002 | DBA-000002 | | 6 | 001-000003 | DBA-000003 | +----+------------+------------+ 3 ROWS IN SET (0.00 sec) Alterando los valores actuales: CALL sp_setCustomVal('seq_1','001',675); INSERT INTO custom_autonums (id) VALUES (NULL),(NULL),(NULL); SELECT * FROM custom_autonums; +----+------------+------------+ | id | seq_1 | seq_2 | +----+------------+------------+ | 4 | 001-000001 | DBA-000001 | | 5 | 001-000002 | DBA-000002 | | 6 | 001-000003 | DBA-000003 | | 7 | 001-000676 | DBA-000004 | | 8 | 001-000677 | DBA-000005 | | 9 | 001-000678 | DBA-000006 | +----+------------+------------+ 6 ROWS IN SET (0.00 sec) Enjoy!
planetmysql.org | 29-feb-2012 14:00
Snapshots y procesos en MySQL
Al ver que un site se queda frito durante un minuto pero cuando entramos ya no queda ningún thread en el MySQL debemos investigar los logs. Si no existen errores en el log del daemon, para investigar el site bloqueado podemos ver que hay en el log de slow queries. Suponiendo el siguiente: (...) # Time: 120228 21:00:04 # User@Host: systemadmin[systemadmin] @ localhost [] # Query_time: 1.459100 Lock_time: 0.000034 Rows_sent: 0 Rows_examined: 0 SET timestamp=1330441204; REPLACE INTO `sesiones` VALUES('ffff21568da68d024dead5b49b680000', '1234', ''); # User@Host: systemadmin[systemadmin] @ localhost [] # Query_time: 1.385580 Lock_time: 0.000032 Rows_sent: 0 Rows_examined: 0 SET timestamp=1330441204; REPLACE INTO `sesiones` VALUES('fffffb70a60660f3d7deade5ca8d0000', '4321', ''); # Time: 120228 21:00:59 # User@Host: systemadmin[systemadmin] @ localhost [] # Query_time: 57.716738 Lock_time: 0.000120 Rows_sent: 2947 Rows_examined: 188240291 SET timestamp=1330441259; SELECT u.id, count(c.id_2) as ccc FROM (SELECT v.id, count(m.id_video) as ccc FROM video v LEFT JOIN video_fb m ON v.id = m.id_video WHERE disabled = 0 GROUP BY v.id) u LEFT JOIN video_control c ON u.id = c.id_video GROUP BY u.id; # User@Host: root[root] @ localhost [] # Query_time: 56.488706 Lock_time: 0.000000 Rows_sent: 0 Rows_examined: 0 use mysql; SET timestamp=1330441259; FLUSH TABLES WITH READ LOCK; # Time: 120228 21:03:19 # User@Host: systemadmin[systemadmin] @ localhost [] # Query_time: 1.401439 Lock_time: 0.000144 Rows_sent: 20 Rows_examined: 1075238 (...) Lo que estamos viendo son dos queries: La SELECT que ha tardado 57.716738 segundos El FLUSH TABLES que ha tardado 56.488706 segundos Lo que esta pasando aquí es que se lanza una select para un proceso que tarda mucho, y al mismo tiempo se lanza otro script para hacer un snapshot de la base de datos. El FLUSH TABLES se encuentra la query corriendo por lo que bloquea y espera que se complete dicha query, que al ser de un proceso tarda 57 segundos (lo cual no importa al no ser de la parte web) Durante el tiempo que tenemos la query ejecutandose no se puede completar el FLUSH TABLES, por lo que tampoco deja entrar nuevas queries a ejecutar y por esto se nos bloquea la web. La solución al problema es tener en cuenta el resto de crons, evitando que se nos acumulen todos al minuto 00. En este caso el proceso tarda menos de un minuto, por lo que cambiando los snapshots al minuto 3 evitaremos que se repita. Tags: MySQL Relacionados Vistas (views) en MySQL Ver el usuario con el que estamos conectados en Oracle y MySQL Ver el estado de un MySQL Uso de mk-find para realizar analyze y optimize de las tablas MySQL Uso de Maatkit para detectar índices duplicados en MySQL
planetmysql.org | 29-feb-2012 08:20
Comment on La Conferencia Rails 2008 será los días 13 y 14 de noviembre by meuble chaussure
Superb editorial! Would like took pleasure the specific following. I
planetmysql.org | 25-feb-2012 08:16
Comment on La Conferencia Rails 2008 será los días 13 y 14 de noviembre by Prostata
Good
planetmysql.org | 24-feb-2012 20:52
Comment on La Conferencia Rails 2008 será los días 13 y 14 de noviembre by เพลงใหม่ download
What is great respecting is dealing with instead of depending on. 180431
planetmysql.org | 24-feb-2012 03:03
Comment on La Conferencia Rails 2008 será los días 13 y 14 de noviembre by เพลงใหม่ rs
Nice site. On your blogs very interest and i will tell a friends. 406961
planetmysql.org | 23-feb-2012 21:30
Comment on La Conferencia Rails 2008 será los días 13 y 14 de noviembre by เพลงใหม่ youtube
I don
planetmysql.org | 23-feb-2012 12:09
Comment on La Conferencia Rails 2008 será los días 13 y 14 de noviembre by เพลงใหม่ download
Hello! I basically would like to give a huge thumbs up for the wonderful information you
planetmysql.org | 23-feb-2012 01:07
Comment on La Conferencia Rails 2008 será los días 13 y 14 de noviembre by เพลงใหม่ ฟรี
Safest messages, or a toasts. are usually launched at one point during the wedding but are likely to just be hilarious, humorous to unusual as nicely. greatest man jokes 220436
planetmysql.org | 23-feb-2012 00:29
Comment on La Conferencia Rails 2008 será los días 13 y 14 de noviembre by เพลงใหม่ มาแรง
Rattling excellent info can be found on web blog . 944506
planetmysql.org | 21-feb-2012 21:20
Comment on ¿Quieres compartir oficina en Madrid? by Rufo
Hola, Alquilo dos puestos de trabajo en estudio de arquitectura. Oficina diáfana de 48 m2 en zona Sanchinarro-Manoteras. Solo tres puestos de trabajo en total, luego el espacio disponible es muy amplio. Además, gran parte del tiempo el tercer puesto está desocupado. Diseño cuidado, ventanal suelo-techo con estor motorizado, conserje, acceso 24 h, edificio exclusivamente de oficinas tipo loft. Aseo y pequeña terraza (aparte de los 48 m2). Plazas de aparcamiento disponibles en el mismo edificio. Zona de oficinas con numerosos restaurantes, cines, etc. metro ligero Virgen del Cortijo y Manoteras en la puerta. Magnífica conexión con M-30, A1, Castellana, etc. Cada puesto incluye: - Equipo imac 27″ último modelo, aún sin estrenar… - Mesa de trabajo 140×70 cm, con cajonera doble, muy amplia. - Estantería de 6 m para compartir entre los tres puestos. - Adsl 50 mb. - Luz, agua, frío/calor, tlf. (llamadas a fijos) - Limpieza semanal - Impresora a3 color - Impresora a4 byn - Nespresso Perfecto para diseñadores, freelances, etc. Precio por puesto: 390 EUR + 18% IVA Contactar en rparrajuarez@gmail.com. Gracias.
planetmysql.org | 17-feb-2012 13:48
Comment on La Conferencia Rails 2008 será los días 13 y 14 de noviembre by disegni tatuaggi
Hey! Do you know if they make any plugins to protect against hackers? I
planetmysql.org | 14-feb-2012 22:11
Replicación MySQL y la clausula LIMIT
Tal y como podemos encontrar en el manual del MySQL, el uso de LIMIT en queries que modifican tablas es inseguro. En modo STATEMENT (por defecto) nos encontraremos en el log mensajes similares a: 120123 19:06:01 [Warning] Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted. Statement: DELETE FROM casas WHERE DATEDIFF(NOW(), casa_date) > 31 limit 1000 Esto se debe a que aunque existan los mismos registros: master> select * from fib; +------+-------+ | id | valor | +------+-------+ | 6 | 8 | | 7 | 13 | | 8 | 21 | | 9 | 34 | +------+-------+ 4 rows in set (0.00 sec) Si no indicamos ningún ORDER BY los registros no tiene porque seguir ningún orden por lo que en un slave nos podrían aparecer los datos en otro orden (siendo igualmente consistentes con el master): slave> select * from fib; +------+-------+ | id | valor | +------+-------+ | 8 | 21 | | 9 | 34 | | 7 | 13 | | 6 | 8 | +------+-------+ 4 rows in set (0.00 sec) Por lo que las queries que borran registros no podemos saber cuales han borrado y cuales no. Por ejemplo, si en los casos anteriores ejecutamos: DELETE FROM fib LIMIT 1; En el master borraríamos el registro con ID 6 pero en el slave borrariamos el de ID 8. La misma query en el master y en el slave produce resultados diferentes (no es determinista). Es por esto que debemos evitar este tipo de queries ya que podemos causar inconsistencias entre el master y el slave. Aún así, también nos puede resultar útil dicha característica. Suponiendo que se ejecuta la siguiente query sobre una tabla MyISAM: DELETE FROM fib WHERE ID > 4; Si se cancela la query (porque esta bloquenado la tabla) a medio ejecutar con un KILL de MySQL habremos borrado algunos registros en el master (pero ninguno en el slave), parandose la replicación con los slaves con el error: Query partially completed on the master Por lo que deberemos rehabilitar la replicación con: SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE; En este punto tendremos la tabla en el master diferente del slave, para igualarlas podemos usar precisamente la característica insegura de LIMIT. Si ejecutamos repetidamente con un pequeño sleep entre las queries: DELETE FROM fib WHERE ID > 4 LIMIT 10; Conseguiremos: Borrar poco a poco de la tabla sin bloquearla durante el tiempo que tarde el borrado de todos los registros, sino que únicamente mientras esta borrando una parte y dejando entrar más queries mientras dejamos el proceso en sleep. Igualar las tablas entre el master y los slaves: La deberemos ejecutar en el master aunque ya no tenga registros a borrar allí para que se transmita a los slaves y borre los registros que se borraron de la query cancelada. Evidentemente podemos ir slave por slave a hacer lo mismo manualmente, pero si tenemos varios slaves puede resultar mucho más cómodo usar el LIMIT e ir igualando los slaves desde un único punto. Tags: MySQL Relacionados Vistas (views) en MySQL Ver el usuario con el que estamos conectados en Oracle y MySQL Ver el estado de un MySQL Uso de mk-find para realizar analyze y optimize de las tablas MySQL Uso de Maatkit para detectar índices duplicados en MySQL
planetmysql.org | 24-ene-2012 09:15
Certificación PHP en Zaragoza
Warp se encargará de impartir los cursos de PHP y MySQL que dan acceso a la certificación Zend PHP 5.3 a partir del 31 de enero de 2012, en el Centro de Tecnologías Avanzadas de Zaragoza. El curso está dirigido a aquellas personas que quieran aprender a programar portales web con dos de las herramientas más [...]
planetmysql.org | 13-ene-2012 10:48
SHOW OPEN TABLES de MySQL
Mediante SHOW OPEN TABLES podemos ver las tablas que están actualmente abiertas en la table cache y si esta en uso o si tiene threads a la espera a que otro libere el bloqueo. Si ejecutamos simplemente SHOW OPEN TABLES veremos por todas las bases de datos las tablas que están abiertas y si están en uso mediante la columna In_use: mysql> show open tables; +-------------+--------------------------------------------------------+--------+-------------+ | Database | Table | In_use | Name_locked | +-------------+--------------------------------------------------------+--------+-------------+ | xxxxxx_utf8 | tmp_systemadmin.es | 0 | 0 | (...) La columna Name_locked se usa para ciertas operaciones como los DROPs. Para ver las tablas abiertas de una cierta base de datos deberemos indicar al SHOW un FROM con la base de datos. Por ejemplo: mysql> show open tables from db1; +----------+-----------------------+--------+-------------+ | Database | Table | In_use | Name_locked | +----------+-----------------------+--------+-------------+ | db1 | temp | 0 | 0 | (...) Además, podemos indicar una condición WHERE para indicar que únicamente queremos ver las que estén en uso o con threads en espera indicando que el valor de In_use no sea cero: mysql> show open tables where In_use!=0; +-------------+-----------------------+--------+-------------+ | Database | Table | In_use | Name_locked | +-------------+-----------------------+--------+-------------+ | db1_utf8 | newsletter_zbl_config | 1 | 0 | +-------------+-----------------------+--------+-------------+ 1 row in set (0.00 sec) mysql> show open tables where In_use!=0; +-------------+---------------------+--------+-------------+ | Database | Table | In_use | Name_locked | +-------------+---------------------+--------+-------------+ | db1_utf8 | tabla1 | 2 | 0 | | db1_utf8 | tabla2 | 2 | 0 | | db1_utf8 | tabla3 | 3 | 0 | +-------------+---------------------+--------+-------------+ 3 rows in set (0.00 sec) Tags: MySQL
planetmysql.org | 11-ene-2012 10:14
Instalación de MySQL Cluster (ndb)
Vamos a ver como instalar MySQL Cluster y sus características. No se trata de una solución de alta disponibilidad para el típico MySQL (con tablas MyISAM o InnoDB) sino que se trata de un storage engine transaccional con sus propias características: ndb El MySQL Cluster ndb ofrece una base de datos sin nada compartido con tres tipos de nodos diferenciados: Nodo de gestión (ndb_mgmd): Permite la gestión del resto de nodos del cluster, arrancar y apagar nodos o hacer backups. Aunque se deba arrancar el primero puede fallar sin afectar al funcionamiento del cluster. Nodo de datos (ndbd o ndbmtd): Almacena los datos los trata Nodo SQL: Nodo a través del cual accedemos a los datos. Se trata de un mysqld con el conector para los ndb. Debe ser arrancado con las opciones ndbcluster para habilitar el storage engine y la opción ndb-connectstring para indicar el nodo a conectarnos para acceder al clúster Tiene algunas restricciones a considerar: Se trata de una base de datos en memoria por lo que tantos datos por tanta redundacia es la memória RAM que necesitamos (más un extra por el sistema y los deamons). En las versiones actuales los datos no indexados pueden ir a disco pero todo dato indexado debe estar en memoria. Las queries con joins al estar repartidas las rows entre los nodos de datos pasar a ser, en general, más costosas. Lo ideal es obtener siempre resulsets pequeños El storage engine no soporta foreign keys. La aplicación no debe depender de éstas para mantener la consisténcia El storage engine no soporta FULLTEXT, por lo que para este tipo de búsquedas es posible que necesitemos un sistema externo como solr o Sphinx A continuación podemos ver como instalar el MySQL Cluster en un solo equipo para evaluarlo. Para la instalación podemos bajar los binarios de la web de MySQL y dejarlos en /opt/mysql-cluster: cd /usr/local/src wget http://dev.mysql.com/get/Downloads/MySQL-Cluster-7.1/mysql-cluster-gpl-7.1.15a-linux-x86_64-glibc23.tar.gz/from/http://mirrors.ircam.fr/pub/mysql/ tar xzf mysql-cluster-gpl-7.1.15a-linux-x86_64-glibc23.tar.gz -C /opt ln -s /opt/mysql-cluster-gpl-7.1.15a-linux-x86_64-glibc23/ /opt/mysql-cluster A continuación añadimos el usuario mysql: groupadd mysql useradd -g mysql mysql Y cambiamos permisos: cd /opt/mysql-cluster chown -R root:mysql . Podemos crear los directorios para el cluster de evaluación dentro de /opt/mycluster: mkdir -p /opt/mycluster/conf mkdir -p /opt/mycluster/ndb1 mkdir -p /opt/mycluster/ndb2 mkdir -p /opt/mycluster/ndb3 mkdir -p /opt/mycluster/ndb4 mkdir -p /opt/mycluster/mysqld mkdir -p /opt/mycluster/ndb-mgm chown mysql. /opt/mycluster/ndb1 chown mysql. /opt/mycluster/ndb2 chown mysql. /opt/mycluster/ndb3 chown mysql. /opt/mycluster/ndb4 chown mysql. /opt/mycluster/mysqld chown mysql. /opt/mycluster/ndb-mgm En un entorno real depende del rol del equipo creariamos un directorio o otro. A continuación instalaremos las tablas para el mysqld: cd /opt/mysql-cluster ./scripts/mysql_install_db --user=mysql --datadir=/opt/mycluster/mysqld Seguimos definiendo un my.cnf muy básico cat < /opt/mycluster/conf/my.cnf [mysqld] ndbcluster datadir=/opt/mycluster/mysqld basedir=/opt/mysql-cluster EOF Y la configuración básica del cluster con redundancia 2: cat < /opt/mycluster/conf/config.ini [ndb_mgmd] hostname=localhost datadir=/opt/mycluster/ndb-mgm nodeid=1 [ndbd default] noofreplicas=2 [ndbd] hostname=localhost datadir=/opt/mycluster/ndb1 nodeid=11 [ndbd] hostname=localhost datadir=/opt/mycluster/ndb2 nodeid=12 [mysqld] nodeid=50 EOF Cambiamos los permisos: chown mysql. /opt/mycluster/conf/ -R Y arrancamos el nodo de management: su - mysql -c '/opt/mysql-cluster/bin/ndb_mgmd -f /opt/mycluster/conf/config.ini --initial --configdir=/opt/mycluster/conf/' Podemos ver que el nodo de gestión esta arrancado con netstat. Veremos que esta escuchando, por defecto, en el puerto 1186: # netstat -tpln | grep ndb_mgmd tcp 0 0 0.0.0.0:1186 0.0.0.0:* LISTEN 30375/ndb_mgmd A continuación podemos arrancar el primer nodo de datos: su - mysql -c '/opt/mysql-cluster/bin/ndbmtd -c localhost:1186' Veremos como nos indica como arranca y que nodeid obtiene: 2011-10-17 15:56:55 [ndbd] INFO -- Angel connected to 'localhost:1186' 2011-10-17 15:56:55 [ndbd] INFO -- Angel allocated nodeid: 11 Si volvemos a ejecutar el comando: su - mysql -c '/opt/mysql-cluster/bin/ndbmtd -c localhost:1186' Dada la configuración que hemos definido sin restringir por host, obtendremos el siguiente nodeid disponible: 2011-10-17 15:57:44 [ndbd] INFO -- Angel connected to 'localhost:1186' 2011-10-17 15:57:44 [ndbd] INFO -- Angel allocated nodeid: 12 Mediante ndb_mgm y la opción -e para pasar comandos podemos ver datos sobre el estado del cluster y sus nodos. Con SHOW veremos un resumen del estado global: # /opt/mysql-cluster/bin/ndb_mgm -e show Connected to Management Server at: localhost:1186 Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=11 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15, Nodegroup: 0, Master) id=12 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15, Nodegroup: 0) [ndb_mgmd(MGM)] 1 node(s) id=1 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15) [mysqld(API)] 1 node(s) id=50 (not connected, accepting connect from any host) A continuación podemos arrancar el mysqld: su - mysql -c '/opt/mysql-cluster/bin/mysqld --defaults-file=/opt/mycluster/conf/my.cnf ' Veremos como arranca y conecta con los nodos de datos ndb: 111017 16:01:17 [Note] Plugin 'FEDERATED' is disabled. 111017 16:01:17 InnoDB: Initializing buffer pool, size = 8.0M 111017 16:01:17 InnoDB: Completed initialization of buffer pool InnoDB: The first specified data file ./ibdata1 did not exist: InnoDB: a new database to be created! 111017 16:01:17 InnoDB: Setting file ./ibdata1 size to 10 MB InnoDB: Database physically writes the file full: wait... 111017 16:01:18 InnoDB: Log file ./ib_logfile0 did not exist: new to be created InnoDB: Setting log file ./ib_logfile0 size to 5 MB InnoDB: Database physically writes the file full: wait... 111017 16:01:18 InnoDB: Log file ./ib_logfile1 did not exist: new to be created InnoDB: Setting log file ./ib_logfile1 size to 5 MB InnoDB: Database physically writes the file full: wait... InnoDB: Doublewrite buffer not found: creating new InnoDB: Doublewrite buffer created InnoDB: Creating foreign key constraint system tables InnoDB: Foreign key constraint system tables created 111017 16:01:18 InnoDB: Started; log sequence number 0 0 111017 16:01:18 [Note] NDB: NodeID is 50, management server 'localhost:1186' 111017 16:01:18 [Note] NDB[0]: NodeID: 50, all storage nodes connected 111017 16:01:18 [Warning] NDB: server id set to zero - changes logged to bin log with server id zero will be logged with another server id by slave mysqlds 111017 16:01:18 [Note] Starting Cluster Binlog Thread 111017 16:01:18 [Note] Event Scheduler: Loaded 0 events 111017 16:01:19 [Note] NDB: Creating mysql.ndb_schema 111017 16:01:20 [Note] NDB Binlog: CREATE TABLE Event: REPL$mysql/ndb_schema 111017 16:01:20 [Note] NDB Binlog: logging ./mysql/ndb_schema (UPDATED,USE_WRITE) 111017 16:01:20 [Note] NDB: Creating mysql.ndb_apply_status 111017 16:01:20 [Note] NDB Binlog: CREATE TABLE Event: REPL$mysql/ndb_apply_status 111017 16:01:20 [Note] NDB Binlog: logging ./mysql/ndb_apply_status (UPDATED,USE_WRITE) 2011-10-17 16:01:20 [NdbApi] INFO -- Flushing incomplete GCI:s < 102/18 2011-10-17 16:01:20 [NdbApi] INFO -- Flushing incomplete GCI:s < 102/18 111017 16:01:20 [Note] NDB Binlog: starting log at epoch 102/18 111017 16:01:20 [Note] NDB Binlog: ndb tables writable 111017 16:01:20 [Note] /opt/mysql-cluster/bin/mysqld: ready for connections. Version: '5.1.56-ndb-7.1.15a-cluster-gpl' socket: '/tmp/mysql.sock' port: 3306 MySQL Cluster Server (GPL) Obtendremos el mysqld en el puerto por defecto al que podemos conectar normalmente como cualquier otro MySQL: # netstat -tpln | grep mysqld tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 9534/mysqld Con ndb_mgm podemos ver que ya tenemos el cluster completo: # /opt/mysql-cluster/bin/ndb_mgm -e show Connected to Management Server at: localhost:1186 Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=11 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15, Nodegroup: 0, Master) id=12 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15, Nodegroup: 0) [ndb_mgmd(MGM)] 1 node(s) id=1 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15) [mysqld(API)] 1 node(s) id=50 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15) Para crear las tablas ndb simplemente deberemos indicar ENGINE=ndb, por ejemplo: [root@apolo src]# mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.1.56-ndb-7.1.15a-cluster-gpl MySQL Cluster Server (GPL) Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> create database jordi; Query OK, 1 row affected (0.06 sec) mysql> use jordi; Database changed mysql> create table jordi(id int) engine=ndb; Query OK, 0 rows affected (0.06 sec) mysql> insert into jordi values (1),(2),(3); Query OK, 3 rows affected (0.00 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from jordi; +------+ | id | +------+ | 1 | | 3 | | 2 | +------+ 3 rows in set (0.00 sec) mysql> En el log del mysqld podemos ver que se ha creado la tabla: 111017 16:04:16 [Note] NDB Binlog: CREATE TABLE Event: REPL$jordi/jordi Y en el datadir tendremos la base de datos: # ls -la /opt/myclusterdb/ total 20548 drwxr-xr-x 6 mysql mysql 4096 Oct 17 16:03 . drwxr-xr-x 7 root root 4096 Oct 17 15:21 .. -rw-rw---- 1 mysql mysql 5 Oct 17 16:01 apolo.pid -rw-rw---- 1 mysql mysql 10485760 Oct 17 16:01 ibdata1 -rw-rw---- 1 mysql mysql 5242880 Oct 17 16:01 ib_logfile0 -rw-rw---- 1 mysql mysql 5242880 Oct 17 16:01 ib_logfile1 drwx------ 2 mysql mysql 4096 Oct 17 16:04 jordi drwx------ 2 mysql root 4096 Oct 17 16:01 mysql drwx------ 2 mysql mysql 4096 Oct 17 13:54 ndbinfo drwx------ 2 mysql root 4096 Oct 17 13:54 test Los privilegios se almacenan en el datadir del mysqld, por lo que deberemos definirlos a cada uno que instalemos con sus usuarios: pwgen 20 > /opt/myclusterdb/.mysql.root.pass chmod 600 /opt/myclusterdb/.mysql.root.pass /opt/mysql-cluster/bin/mysqladmin -u root -h 127.0.0.1 password $(cat /opt/myclusterdb/.mysql.root.pass) /opt/mysql-cluster/bin/mysqladmin -u root password $(cat /opt/myclusterdb/.mysql.root.pass) echo "alias mycluster='/opt/mysql-cluster/bin/mysql -p\$(cat /opt/myclusterdb/.mysql.root.pass)'" >> /etc/profile . /etc/profile echo 'delete from mysql.user where Password="";' | mycluster echo 'flush privileges;' | mycluster Podemos hacer algunas pruebas matando los ndb: # kill 28420 28419 25273 25272 # kill 28420 28419 25273 25272 -bash: kill: (28420) - No such process -bash: kill: (28419) - No such process -bash: kill: (25273) - No such process -bash: kill: (25272) - No such process Veremos en el log como desparecen: 111017 16:17:43 [Note] NDB Binlog: Node: 11, down, Subscriber bitmask 00 111017 16:17:43 [Note] NDB Binlog: Node: 12, down, Subscriber bitmask 00 111017 16:17:43 [Note] NDB Binlog: cluster failure for ./mysql/ndb_schema at epoch 585/0. 111017 16:17:43 [Note] NDB Binlog: cluster failure for ./mysql/ndb_apply_status at epoch 585/0. 111017 16:17:43 [Note] Restarting Cluster Binlog Como ha perdido los nodos de datos ya no podremos hacer queries a la tabla: mysql> select * from jordi; ERROR 1296 (HY000): Got error 157 'Unknown error code' from NDBCLUSTER Y en el ndb_mgm los veremos como not connected: # /opt/mysql-cluster/bin/ndb_mgm -e show Connected to Management Server at: localhost:1186 Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=11 (not connected, accepting connect from localhost) id=12 (not connected, accepting connect from localhost) [ndb_mgmd(MGM)] 1 node(s) id=1 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15) [mysqld(API)] 1 node(s) id=50 (not connected, accepting connect from any host) Arrancando de nuevo los nodos: # su - mysql -c '/opt/mysql-cluster/bin/ndbmtd -c localhost:1186' 2011-10-17 16:18:50 [ndbd] INFO -- Angel connected to 'localhost:1186' 2011-10-17 16:18:50 [ndbd] INFO -- Angel allocated nodeid: 11 # su - mysql -c '/opt/mysql-cluster/bin/ndbmtd -c localhost:1186' 2011-10-17 16:18:53 [ndbd] INFO -- Angel connected to 'localhost:1186' 2011-10-17 16:18:53 [ndbd] INFO -- Angel allocated nodeid: 12 Vemos que reaparecen en el ndb_mgm: # /opt/mysql-cluster/bin/ndb_mgm -e show Connected to Management Server at: localhost:1186 Cluster Configuration --------------------- [ndbd(NDB)] 2 node(s) id=11 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15, Nodegroup: 0, Master) id=12 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15, Nodegroup: 0) [ndb_mgmd(MGM)] 1 node(s) id=1 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15) [mysqld(API)] 1 node(s) id=50 @127.0.0.1 (mysql-5.1.56 ndb-7.1.15) Y en el mysqld los volvemos a ver: 111017 16:19:03 [Note] NDB Binlog: DISCOVER TABLE Event: REPL$mysql/ndb_schema 111017 16:19:03 [Note] NDB Binlog: logging ./mysql/ndb_schema (UPDATED,USE_WRITE) 111017 16:19:03 [Note] NDB Binlog: DISCOVER TABLE Event: REPL$mysql/ndb_apply_status 111017 16:19:04 [Note] NDB Binlog: logging ./mysql/ndb_apply_status (UPDATED,USE_WRITE) 2011-10-17 16:19:04 [NdbApi] INFO -- Flushing incomplete GCI:s < 585/14 2011-10-17 16:19:04 [NdbApi] INFO -- Flushing incomplete GCI:s < 585/14 111017 16:19:04 [Note] NDB Binlog: starting log at epoch 585/14 111017 16:19:04 [Note] NDB Binlog: ndb tables writable Y podremos volver a acceder a los datos ya que periódicamente los ndb pasan los datos a disco. mysql> select * from jordi; +------+ | id | +------+ | 3 | | 2 | | 1 | +------+ 3 rows in set (0.12 sec) Incluso matando todos los daemons: [root@apolo src]# kill 30375 9534 [root@apolo src]# kill 30375 9534 -bash: kill: (30375) - No such process [root@apolo src]# kill 30375 9534 -bash: kill: (30375) - No such process [root@apolo src]# kill 30375 9534 -bash: kill: (30375) - No such process -bash: kill: (9534) - No such process Al volver a arrancar: # su - mysql -c '/opt/mysql-cluster/bin/ndb_mgmd -f /opt/mycluster/conf/config.ini --initial --configdir=/opt/mycluster/conf/' # su - mysql -c '/opt/mysql-cluster/bin/mysqld --defaults-file=/opt/mycluster/conf/my.cnf ' # su - mysql -c '/opt/mysql-cluster/bin/ndbmtd -c localhost:1186' 2011-10-17 16:23:18 [ndbd] INFO -- Angel connected to 'localhost:1186' 2011-10-17 16:23:18 [ndbd] INFO -- Angel allocated nodeid: 11 # su - mysql -c '/opt/mysql-cluster/bin/ndbmtd -c localhost:1186' 2011-10-17 16:23:19 [ndbd] INFO -- Angel connected to 'localhost:1186' 2011-10-17 16:23:19 [ndbd] INFO -- Angel allocated nodeid: 12 Tendremos de nuevo los datos: # mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.1.56-ndb-7.1.15a-cluster-gpl MySQL Cluster Server (GPL) Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> use jordi Database changed mysql> select * from jordi; +------+ | id | +------+ | 1 | | 3 | | 2 | +------+ 3 rows in set (0.05 sec) mysql> Evidentemente se trata de un entorno de pruebas sin transacciones activas, por lo que no debemos hacer estas cosas en un mysql de producción si no queremos perder transacciones. Tags: MySQL
planetmysql.org | 10-ene-2012 07:41
Cuidado con los snapshots en MySQL
He visto algunas formas de hacer snapshots de MySQL que no deben hacerse así. Vamos a ver un ejemplo. Me han pasado scripts como el siguiente: /usr/sbin/xfs_freeze -f /var/mysql /usr/bin/ec2-create-snapshot -K $KEY -C $CERT vol-1111ff11 --description "SnapMysql" /usr/sbin/xfs_freeze -u /var/mysql En este caso se hace un snapshot de un EBS habiendo congelado previamente el sistema [...]
planetmysql.org | 09-ene-2012 10:44
Fichero con el estado de InnoDB
Mediante SHOW INNODB STATUS podemos obtener ver los contadores de InnoDB, valores varios, estadísticas y las transacciones. Algunos de dichos valores nos puede interesar guardar un histórico para hacer un gráfico o ver su evolución. Mediante la opción innodb-status-file podemos simplificar el script de optención de datos. Mediante la opción –innodb-status-file indicamos al MySQL que [...]
planetmysql.org | 27-dic-2011 10:11
Último certificado del año, MySQL 5.0 Developer
Justo cuando llegaba el final del año conseguí mi objetivo, el certificado MySQL 5.0 Developer. Ya tengo el pack completo :) La verdad es que este me ha parecido ligeramente más complicado que los anteriores, más que nada por mi poca experiencia con el lenguaje SQL. Pero para eso es están las certificaciones, para aprender. Ahora toca centrarse en aplicar lo aprendido y seguir mejorando poco a poco. Tengo muchos libros para leer en mi Kindle pero poco tiempo. He empezado por "MySQL High Availability" que a pesar de ser un poco pesado de leer en algunas partes y que son muy pesados con su librería de Python, es un buen libro para ampliar los conocimientos en replicación y alta disponibilidad. Fuera de la lectura técnica, ¿tenéis alguna recomendación para leer en este 2012? A mi me ha picado la curiosidad Metro 2033.
planetmysql.org | 24-dic-2011 16:57
Lock wait timeout exceeded; Try restarting transaction
Al ejecutar una query en un MySQL contra una tabla con el engine InnoDB nos podemos encontrar con el error: ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction La variable innodb_lock_wait_timeout permite definir el tiempo va a esperar una query a obterner un lock, por lo que podemos minimizar este error aumentando este [...]
planetmysql.org | 21-dic-2011 08:00
Readers’ Choice Awards 2011
Y salieron los premios anuales de la revista Linux Journal, me topé con algunas sorpresas y otras no tanto, y puedo resaltar los ganadores de algunas categorías que me interesan: Mejor distribución de Linux: Ubuntu (faltaba mas) Mejor entorno de escritorio: Gnome 3 (de verdad no esta tan mal) Mejor navegador: Firefox :/ Mejor gestor de base de datos: MySQL (seguido muy de cerca por PostgreSQL) Mejor juego: World of Goo (creo que vale la pena las 20 fichas que cuesta) La lista es larga, son 45 categorías, les sugiero que le hechen un vistazo: http://www.linuxjournal.com/slideshow/readers-choice-2011 Y pronto (abril 2012) Percona Live: MySQL Conference And Expo 2012 Pueden ver y descargar las conferencias del evento 2011 ahi mismo!
planetmysql.org | 11-dic-2011 02:19
Eliminar numeros de linea con Vim
¿Quién no ha buscado código fuente en la red? Algunos sitios comparten segmentos de codigo fuente incluyendo el numero de línea, sé que lo hacen intencionalmente por que disfruntan sabiendo que debemos darnos el trabajo de eliminar las numeraciones de linea para poder compilar el codigo brindado, ademas de fijarnos en otros detalles. Aqui una muestra clásica de un copy paste desde una pagina web hacia Vim (u otro editor): Para un segmento de codigo de unas cuantas lineas no hay ningun problema, pero si se tratan de cientos de lineas, nos tomaría varios minutos… me da pereza de solo pensarlo. Solucion rápida: Vim nos ofrece una manera facil de reemplazar texto usando expresiones regulares. Para este caso es muy fácil armar una expresión que reconozca: Espacios en blanco al inicio ^\s* Al menos un digito (numero de línea) [0-9]\+ Unos espacios mas, 0 ó 3 espacios. \s\{0,3} La expresión regular quedaría así: ^\s*[0-9]\+\s\{0,3}, luego aplicamos la busqueda y reemplazo en todo el documento con el siguiente comando: :%s/^\s*[0-9]\+\s\{0,3}//g el resultado es el siguiente: Las expresiones regulares son mucho mas poderosas, este es sólo un caso trivial que nos hace ganar un poco mas de tiempo.
planetmysql.org | 07-dic-2011 18:43
Probando UDFs para MySQL: Title Case
Conocemos “de sobra” lo que hacen las funciones LCASE y UCASE en MySQL, otros gestores también la implementan con alguna variación en el nombre pero con el mismo resultado. Pero que pasa si queremos una función que convierta un texto al tipo Titulo, conocido también como title case, es decir convertir “un texto arbitrario” en “Un Texto Arbitrario“, para este caso no existe la función mágica que haga esa conversión y tenemos que escribir una propia. No es necesario “reinventar la rueda” (aunque podría hacerlo), buscando encontré un repositorio de funciones UDF para MySQL: http://www.mysqludf.org/ , hay varias funciones agrupadas según el objetivo/funcionalidad, solo tienen que descargar el código fuente, compilarlo y agregarlo como funciones nuevas en vuestros servidores MySQL. He aislado la función str_ucwords (que convierte un texto a “Title Case”) en un archivo separado para mostrarles como es que podemos compilar una UDF para MySQL.Pero he modificado el archivo por que solo funcionaba con parámetros constantes, ahora la función acepta nombres de columnas como parámetros. Pueden descargar el archivo fuente: ucwords.c Para compilarlo necesitan unas tres instrucciones: #Compilamos el programa ivancp@ubuntu$ gcc ucwords.c -o ucwords.so -shared -lmysqlclient -I/usr/include/mysql #Copiamos el archivo de salida en la carpeta de plugins de mysql ivancp@ubuntu$ sudo cp ucwords.so /usr/lib/mysql/plugin #Quitamos el permiso de ejecución del archivo #para que pueda cargarlo correctamente ivancp@ubuntu$ sudo chmod -x /usr/lib/mysql/plugin/ucwords.so La opción -shared compila el archivo para que pueda ser usado como librería. La descripción del resto de parámetros van a encontrarla en la entrada: Leer datos de MySQL desde C Ahora debemos agregar la función a MySQL: mysql> create function str_ucwords returns string soname 'ucwords.so'; Query OK, 0 rows affected (0.00 sec) mysql> Ahora veamos algunas pruebas, esta es una consulta común (los datos están almacenados en mayúsculas o Upper Case): mysql>select nombres from tabla; +----------------------------------+ | nombres | +----------------------------------+ | AGUILAR PALACIOS RICARDO | | ANDIA MARQUEZ LUIS MELITON | | CUYUBAMBA RAMOS VICTOR ALEJANDRO | | FELICIANO VELAZCO VICTORIA | | FLORIDA EVANGELISTA LILA REYNA | | LEON LAULATE FERNANDO | | PALACIOS LOPEZ ROXANA BEATRIZ | | REATEGUI RAMIREZ CARLOS | | REINOSO MORI JORGE WILLY | | SALAZAR VALDIVIA WALTER | | SANCHEZ TUTUSIMA CARMEN ROSA | | VELAZCO BERROA PETRONA | +----------------------------------+ 12 rows in set (0.00 sec) Aquí esta lo que queremos ver, la consulta primero convierte a minúsculas todo el campo y luego convierte éste resultado a Title Case, vean: mysql>select str_ucwords(lcase(nombres)) from tabla; +----------------------------------+ | str_ucwords(lcase(nombres)) | +----------------------------------+ | Aguilar Palacios Ricardo | | Andia Marquez Luis Meliton | | Cuyubamba Ramos Victor Alejandro | | Feliciano Velazco Victoria | | Florida Evangelista Lila Reyna | | Leon Laulate Fernando | | Palacios Lopez Roxana Beatriz | | Reategui Ramirez Carlos | | Reinoso Mori Jorge Willy | | Salazar Valdivia Walter | | Sanchez Tutusima Carmen Rosa | | Velazco Berroa Petrona | +----------------------------------+ 12 rows in set (0.00 sec) Funciona a la perfección! Por favor revisen la documentación, en otro post explicaré que deben tener en cuenta para elaborar sus propios UDF: http://dev.mysql.com/doc/refman/5.0/en/adding-udf.html
planetmysql.org | 05-dic-2011 14:00
Mis bugs reportados de MySQL-Workbench
Hace algunos meses, mientras usaba MySQL Workbench 3.2.33, noté varios bugs los cuales reporté inmediatamente, Oracle ya publicó la versión 3.2.35 y está apunto de publicar la versión 3.2.36, no había recibido noticias acerca de mis reportes. Siempre es bueno colaborar a la mejora de herramientas libres, en este caso me dí cuenta de algunos detalles, incluso algunos de ellos pasarían desapercibidos. Pasado el tiempo ya, quise saber sobre mis bugs reportados y resulta que todos ya habían sido resueltos, y éstos son: 60354 Workbench can’t open a stored procedure 60557 Workbench closes without ask to save modified file 60562 The action pane won’t checks the selected database. 60576 Workbench adds a extra quote 60610 Don’t assign a correct tab name when open a sql script Son solamente 5 de cientos de reportes, el equipo que desarrolla MySQL Workbench se encarga de ir resolviendo de a pocos los bugs y van soltando las versiones según les parezca, llegará el día en que los bugs sean solamente unos cuantos por versión, ese día Workbench habrá madurado y será mucho mas estable que hasta ahora. Cualquiera puede reportar un bug, solo debes ir a la pagina de bugs: http://bugs.mysql.com/report.php detallar lo mejor posible las condiciones donde se genera el “horror”. Puede que sea necesario buscar un error similar ya reportado.
planetmysql.org | 03-dic-2011 14:00
Problema al emitir recibos de honorarios SUNAT
Hace unas horas me he afiliado a la emisión por recibos de honorarios de la SUNAT, y me he dado con la sorpresa que no se pueden emitir los recibos de honorarios y me imagino que también para otros casos. Sé que llamando a la misma SUNAT o enviando una queja puede demorar una eternidad, y busque una solución mientras el genio que ha programado esto lo solucione. Este es el punto donde se estanca, desde aquí no es posible avanzar mas: Deben usar Firefox (con firebug plugin) o Chrome para que puedan seguir adelante, con los siguientes pasos (a prueba de tontos), lo voy a decir una vez mas Internet Explorer No Sirve!!! Paso 1: Inspeccionar el campo (Click derecho sobre) Nombre o Razon social del usuario, después de haber validado/consultado el número de RUC: Paso 2: Editar el HTML (que debería estar seleccionado) haciendo click derecho: Paso 3: Agregar el texto id=”nombrecliente” y cerrar la ventana de edicón: Paso 4: Seguir adelante! Seguramente este metodo sirva unas cuantas horas hasta que se den cuenta del horror, espero les sirva para salir de este apuro.
planetmysql.org | 02-dic-2011 16:22
¿Donde comprar libros baratos?
Mientras sitios como Amazon ofrecen una variedad de libros única en la red, también existen los otros donde podemos encontrar libros usados a bajo costo y finalmente podamos tener el gusto de leer el libro original. Algunos dirán que es una tontería comprar libros antiguos sobre computación, bueno… cada quien con sus gustos. Por ejemplo siempre he querido tener los cuatro tomos de la documentación de Visual C++ 6.0 edición impresa de mas de 1200 paginas cada uno, o los libros de David Kruglinski, Jeff Prosise o Herbert Schildt… una delicia para quienes aman coleccionar verdaderos clásicos. En Amazon también podemos comprar libros usados a menor precio, pero hay sitios dedicados a vender libros usados (aunque ahora también venden nuevos), les dejo una lista de sitios en los que he comprado (y compro periódicamente) gran cantidad de libros nuevos y usados. www.thriftbooks.com Costos de envío por libro: $4.99 Libros desde $3.95 www.betterworldbooks.com Costos de envío por libro: Gratis! Libros desde $7.48 www.thriftbooks.com Costos de envío por libro: $5.99 Libros desde $3.39 www.alibris.com Costos de envío por libro: $12.99 Libros desde $1.00 Como han visto los costos de envío varían, en todos los casos los tiempos de envío pueden dejarlos paranoicos, solo hay que ser pacientes, los libros llegarán de todos modos.
planetmysql.org | 01-dic-2011 14:00
Nuevos cambios, nuevas oportunidades
Hace bastante tiempo que no escribo aquí y creo que es necesario dar una explicación a las personas que me siguen, aunque no sean muchas ;) Mi vida laboral ha vuelto a dar un cambio importante, el segundo en lo que voy de año. Desde Octubre he entrado a trabajar en Percona como Support Engineer lo cual, bajo mi punto de vista, es un salto profesional grandísimo y le estoy muy agradecido a Ewen Fortune por esta oportunidad. Ahora mismo tengo de todo en mi vida, pero no tiempo libre ;) Los que me conocen bien saben que en cuanto tengo un reto por delante no puedo dejar de trabajar y esforzarme dando lo mejor de mi, por lo que estos meses están siendo muy intensos. Mucha lectura, estudio y práctica para poder alcanzar el nivel de profesionalidad y conocimiento que tanto hacen destacar a Percona. Seguiré publicando posts sobre MySQL en mi blog, pero en un principio con menos frecuencia que antes, al menos hasta que me asiente completamente en mi nuevo trabajo. De vez en cuando podéis encontrar algún post mio en MySQL Performance Blog y si saco tiempo iré publicando aquí las versiones en Español. Para empezar, aquí tenéis mi primera contribución: Avoiding auto-increment holes on InnoDB with INSERT IGNORE Muchas gracias a todos y un saludo especial a mis antiguos compañeros de Arsys.
planetmysql.org | 01-dic-2011 13:49
Activar el motor FEDERATED en MySQL
El motor FEDERATED de MySQL, aunque no es muy versátil, puede resultar útil, por ejemplo, para conectarnos directamente a una tabla en otro servidor MySQL sin necesidad de un intermediario, como un script PHP que copie/verifique/vea datos de otro servidor. El motor FEDERATED no esta habilitado por defecto en instalaciones estándares sobre Linux, no hay que compilar nada, solo agregarle el parametro --federated en el archivo /etc/init/mysql.conf: #Busquen esta linea en el archivo /etc/init/mysql.conf exec /usr/sbin/mysqld --federated Luego de reiniciar el servicio mysql, verán los resultados: ivancp@ubuntu$ sudo service mysql restart Para ver que motores están disponibles ejecuten SHOW ENGINES en la linea de comando MySQL: mysql> show engines; +------------+---------+-----------+--------------+------+------------+ | Engine | Support | Comment | Transactions | XA | Savepoints | +------------+---------+-----------+--------------+------+------------+ | InnoDB | YES | Supports t| YES | YES | YES | | MRG_MYISAM | YES | Collection| NO | NO | NO | | BLACKHOLE | YES | /dev/null | NO | NO | NO | | CSV | YES | CSV storag| NO | NO | NO | | MEMORY | YES | Hash based| NO | NO | NO | | FEDERATED | YES | Federated | NO | MO | NO | | ARCHIVE | YES | Archive st| NO | NO | NO | | MyISAM | DEFAULT | Default en| NO | NO | NO | +------------+---------+-----------+--------------+------+------------+ 8 rows in set (0.00 sec) Para conectarnos a una tabla remota y consultar que datos contiene, tenemos que crear la tabla, debe ser muy similar a la tabla remota, pueden ayudarse con el comando SHOW CREATE TABLE para ahorrar tiempo y agregar el parámetro CONNECTION al final. -- Tabla con conexion a una base de datos remota CREATE TABLE tabla_remota ( id INT NOT NULL AUTO_INCREMENT, campo1 VARCHAR(32), campo2 INT, PRIMARY KEY (id), INDEX campo1 (campo1) ) ENGINE=FEDERATED DEFAULT CHARSET=utf8 CONNECTION='mysql://usuario:contraseña@1952.168.6.5/base_datos/tabla'; Recomendaciones: El único problema es que la consulta puede demorar un poco mas de lo debido, así es que traten de no hacer consultas cuyos resultados sean realmente grandes. Es una pena que aun no esté disponible la posibilidad de conectarse a otros gestores de datos como PostgreSQL o SQL Server, eso sí que sería útil. Deben crear un usuario sin contraseña en la base de datos de destino, para evitar poner la contraseña en la conexión, ya que es fácil de averiguar (con SHOW CREATE TABLE). Las conexiones son permitidas incluso hacia servidores MySQL mas antiguos. Leer la documentación para mas detalles: http://dev.mysql.com/doc/refman/5.1/en/federated-storage-engine.html Pueden ayudarse con un Stored Procedure para crear estas tablas FEDERATED. Espero les sirva.
planetmysql.org | 29-nov-2011 14:00
WordPress ahora acepta sentencias LaTeX
Gracias a un plugin para WordPress incluido en Jetpack podemos incluir expresiones matemáticas en los posts fácilmente. Solo necesitan instalar Jeckpack en su WordPress para habilitar esta opción. Esto es especialmente útil al momento de explicar un algoritmo, que incluya expresiones matemáticas, o para quienes tengan un blog y sean profesores/físicos/matemáticos/etc Solamente tienen que escribir la expresión matemática en sintaxis entre los signos de dolar: $latex [expresion] $ Aquí algunos ejemplos: El código fuente de los ejemplos anteriores es: $latex x = a_0 + \frac{1}{\displaystyle a_1 + \frac{1}{\displaystyle a_2 + \frac{1}{\displaystyle a_3 + a_4}}}$ $latex x = a_0 + \frac{1}{a_1 + \frac{1}{a_2 + \frac{1}{a_3 + a_4}}} $ $latex z \left( 1 \ +\ \sqrt{\omega_{i+1} + \zeta -\frac{x+1}{\Theta +1} y + 1} \ \right) \ \ \ =\ \ \ 1 $
planetmysql.org | 27-nov-2011 13:00
Thunderbird: proteger nuestro perfil
Nuestro correo electrónico es, quizá, lo mas importante que tenemos en la red, por muchísimas razones es una buena idea gestionar nuestro correo desde Thunderbird, ¿pero que tan seguro está? Siempre he revisado mi correo en un equipo mio y no he tenido problemas al respecto, pero en algunos casos existe la posibilidad de que estemos usando un equipo compartido o Thunderbird esta configurado con diferentes perfiles, ¿cómo podemos proteger nuestro correo? Fácil!, instalando el plugin ProfilePassword, éste plugin no esta disponible desde el repositorio de Thunderbird pero es una maravilla, una vez instalado estará disponible desde el menú Herramientas -> Profile Password y podremos establecer la contraseña de Thunderbird al inicio del programa (no se trata de la contraseña maestra) Aunque no es una protección contra todo riesgo, es una piedra mas en el camino de quienes quieren husmear nuestros correos electrónicos sin autorización. Existe la opción de bloquear Thunderbird mientras estamos fuera. Al iniciar Thunderbird veremos una ventana donde nos pedirá nuestra clave. El complemento no depende del sistema operativo, así es que funciona perfectamente con Windows, Mac y Linux.
planetmysql.org | 25-nov-2011 14:00
WordPress: agregar mas tamaños de imágenes
WordPress crea por defecto 3 copias de tamaños diferentes de los archivos de imágenes, estos pueden ser utilizados para mejorar la disposición de un post. Sin embargo esos tamaños no son siempre los que necesitamos. Redimensionar las imágenes es un trabajo adicional, que puede tomar varios minutos, pero yano, por que existe un plugin que nos permite crear los tamaños que necesitemos, se llama: Additional image sizes (zui). Una vez instalado tendremos más para elegir: Si ya tenemos un blog con muchas entradas e imágenes, hay la opción de volver a crear los archivos de las imágenes adicionales. El pluging se puede instalar fácilmente desde el repositorio, solo búsquenlo con el nombre de zui.
planetmysql.org | 23-nov-2011 14:00
Instalación de MySQL 5.5 en CentOS 6 con upstart
Anteriormente ya vimos como instalar MySQL 5.5 en una CentOS 5 desde código fuente usando daemontools. Hoy veremos la instalación para CentOS 6 con upstart. Primero de todo necesitaremos cmake y las ncurses: yum install cmake -y yum install ncurses-devel -y cd /usr/local/src wget 'http://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.16.tar.gz/from/http://mysql.easynet.be/' tar xzf mysql-5.5.16.tar.gz cd mysql-5.5.16 A continuación seguiremos compilando con [...]
planetmysql.org | 23-nov-2011 07:48
Simplificar el acceso a MySQL CLI
¿No les ha dado pereza escribir, en la linea de comando, todo lo necesario para conectarse a un servidor MySQL? Puede que tome menos de un minuto, pero algunas veces un minuto es vital (sobre todo si estamos cerca del fin del mundo). ubuntu@ubuntu$ mysql -u root -p -h mysqlhost [base_datos] Cuando uno esta apurado, estos comandos suelen fallar varias veces por minuto. La solución: podemos ayudarnos creando atajos con alias en el archivo ~/.bashrc: #archivo ~/.bashrc #comando "my" para conectarse a un servidor local alias my="mysql -u root -p" #comando "my2" para conectarse a un servidor remoto alias my2="mysql -u root -p -h 192.168.1.56" La proxima vez que queramos acceder al servidor local solo tendremos que escribir en la linea de comando my [base_datos], solamente nos pedirá el password del servidor. Podemos ser mas osados y dejar el password en el mismo comando alias: #archivo ~/.bashrc #comando "my" para conectarse a un servidor local alias my="mysql -u root --password=tupwd" #comando "my2" para conectarse a un servidor remoto alias my2="mysql -u root --password=tuotropwd -h 192.168.1.56" Pueden usar los acronimos que prefieran, para mi my y my2 son cortos y útiles. Cada vez que quiero una linea de comando MySQL sólo tengo que cargar una nueva terminal (Super + T), escribir “my mi_base” y [enter]! Ahora se presenta otro problema, como saber en que servidor me encuentro? El acceso puede ser super veloz con los accesos directos via alias, pero todas las terminales tienen el mismo prompt por defecto: mysql> y no hay muchas luces a primera vista para saber en que conexión estamos. Para evitar desastres (por ejemplo ejecutar DROP en el lugar equivocado) podemos cambiar el prompt de la linea de comando de MySQL con la opcion --prompt, entonces, nuestra configuración finalmente quedará así: #archivo ~/.bashrc mejorado #comando 'my' para conectarse a un servidor local alias my='mysql -u root --password=tupwd --prompt="local> "' #comando "my2" para conectarse a un servidor remoto alias my2='mysql -u root --password=tuotropwd -h 192.168.1.56 --prompt="server 1> "' Espero les sirva!
planetmysql.org | 21-nov-2011 14:00