What’s the default password of root user in mariadb?

If you have just installed mariadb, you should run this command in order to set a password for the root user and secure your installation:

$ sudo mysql_secure_installation

Besides asking you to provide the new root password, this utility will help you to remove anonymous user (created by default, intended for testing), disallow root login remotely (root should only be allowed to connect from ‘localhost’), remove test database and privileges ad reloading the privilege table. All of it just pressing the Enter key a couple of times 🙂 Not bad!

If that process doesn’t work, try this other one:

(using sudo, don’t specify any password)

$ sudo mysql -u root

Create a new database:

CREATE DATABASE yourdb;

Grant privileges to a new user:

GRANT ALL ON yourdb.* TO yournewuser@localhost IDENTIFIED BY 'yourpassword';
FLUSH privileges;

 

Demasiadas conexiones a MySQL desde R

Estoy desarrollando una nueva aplicación en R+Shiny. Entre otras cosas, el servidor Shiny necesita acceder a los datos de una BBDD en MySQL. Tengo código en R que accede a MySQL sin problemas, abre y cierra las conexiones bien, sin leaks  por dejar conexiones abiertas. Bueno, eso es lo que creía… cuando por alguna razón la aplicación fallaba, podían darse casos en los que alguna conexión se quedaba abierta. Por una o dos, no pasaba «nada». Pero probando y probando, llegué a este error:

«cannot allocate a new connection — maximum of 16 connections  already opened»

Vaya… el primer problema es: ¿cómo desconecto las conexiones abiertas? La respuesta a esto en la lista de distribución de R:

 cons <- dbListConnections(MySQL()) 
 for(con in cons) 
  dbDisconnect(con)

Y ahora, ¿cómo evitar el error? Lo ideal sería establecer una especie de conexión singleton que se reutilizara desde todo el código. La respuesta a esto, en StackOverflow (cómo no ;-))

library(RMySQL)
getConnection <- function(group) {
  if (!exists('.connection', where=.GlobalEnv)) {
    .connection <<- dbConnect(MySQL(), group=group)
  } else if (class(try(dbGetQuery(.connection, "SELECT 1"))) == "try-error") {
    dbDisconnect(.connection)
    .connection <<- dbConnect(MySQL(), group=group)
  }
  return(.connection)
}

Este código comprueba si existe una conexión en el entorno global. Si no existe, la crea y la devuelve.
Si existe, comprueba que se pueda usar. Si no se puede usar, desconecta y vuelve a crear la conexión, para devolverla.
Es decir, funciona como una caché (o puede verse también como un objeto singleton de tipo connection).
Podríamos ignorar el parámetro group de la función getConnection y en su lugar, usar:

 dbConnect(MySQL(), user=login, password=pass, db=database, host=host)

allí donde fuera necesario.

Receta rápida para optimizar MySQL

highperformancemysqlSiguiendo con el post anterior (recordemos, tengo un servidor muy humilde en recursos que quiero aprovechar al máximo), le toca el turno al servidor MySQL.

Tengo un libro (High Performance MySQL, de la editorial O’Reilly) que -entre otras cosas- se dedica a explicar cómo obtener el mejor rendimiento de un servidor MySQL, así que en este post no voy a hacer más que abrir el melón 🙂

La cuestión es que, antes de entrar a configurar los cientos de parámetros del fichero de configuración my.cnf, quería ir a tocar los interruptores «evidentes». ¿Hay alguna forma de encontrar fallos de configuración obvios en MySQL para hacer que este sistema gestor rinda mejor? («rendir mejor» puede entenderse de varias formas… yo me refiero al sentido de que siga ofreciendo servicio pero que consuma menos RAM).

Pues sí… hay una pequeña aplicación, llamada mysqltuner.pl, que permite «tunear» el fichero my.cnf de forma muy sencilla. Realmente lo que hace es darte pistas y consejos sobre qué «interruptores» tocar para que el servidor rinda mejor.

Aprovechando un domain hack, el autor de la aplicación ha generado un dominio propio con el mismo nombre que la aplicación en Perl: http://mysqltuner.pl. Así que, para descargar y hacer ejecutable esta joyita, basta con hacer:

wget -O mysqltuner.pl http://mysqltuner.pl
chmod a+x mysqltuner.pl
sudo ./mysqltuner.pl

Si ejecutamos con permisos de sudoer, ni siquiera tenemos que configurar las credenciales de mysql, porque como la aplicación indica en el log:

[OK] Logged in using credentials from debian maintenance account.

Qué cosas… no sabía que hubiera una cuenta de mantenimiento debian con la que hacer… eso, mantenimiento de mysql 🙂 Entre otras cosas, lo primero que me dice mysqltuner es:

-------- Storage Engine Statistics -------------------------------------------
[--] Status: +ARCHIVE +BLACKHOLE +CSV -FEDERATED +InnoDB +MRG_MYISAM 
[--] Data in MyISAM tables: 9M (Tables: 14)
[--] Data in PERFORMANCE_SCHEMA tables: 0B (Tables: 17)
[!!] InnoDB is enabled but isn't being used
[!!] Total fragmented tables: 5
...
-------- Recommendations -----------------------------------------------------
General recommendations:
    Add skip-innodb to MySQL configuration to disable InnoDB
    Run OPTIMIZE TABLE to defragment tables for better performance
    MySQL started within last 24 hours - recommendations may be inaccurate
    Reduce your overall MySQL memory footprint for system stability
    Enable the slow query log to troubleshoot bad queries

Vamos, que el módulo InnoDB lo tengo activado (consumiendo memoria) y no lo uso. Sabiendo que mi server si algo tiene que cuidar es la RAM… vamos a hacerle caso… También me dice que tengo tablas fragmentadas que convendría arreglar. Apuntado. Lo primero, antes de pifiarla (desactivando InnoDB cuando por defecto MySQL crea bases de datos InnoDB, por ejemplo), vamos a comprobar…

mysql> use information_schema ;
Database changed
mysql> select * from ENGINES;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| ENGINE             | SUPPORT | COMMENT                                                        | TRANSACTIONS | XA   | SAVEPOINTS |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.00 sec)

Je… Murphy nunca falla. Vamos a arreglar eso (quiero dejar MyISAM por defecto antes de desactivar el soporte InnoDB en MySQL). En el fichero /etc/mysql/my.cnf añado lo siguiente:

default-storage-engine=myisam 
skip_innodb

Y listo. Vamos ahora a optimizar tablas…

mysqlcheck -u root -p -o --all-databases

Pasamos de nuevo mysqltuner.pl:

-------- Storage Engine Statistics -------------------------------------------
[--] Status: +ARCHIVE +BLACKHOLE +CSV -FEDERATED -InnoDB +MRG_MYISAM 
[--] Data in MyISAM tables: 9M (Tables: 14)
[--] Data in PERFORMANCE_SCHEMA tables: 0B (Tables: 17)
[OK] Total fragmented tables: 0

y ¡premio!

Dejo un ejercicio para el lector 🙂

-------- Performance Metrics -------------------------------------------------
[--] Up for: 4h 9m 7s (43K q [2.891 qps], 1K conn, TX: 152M, RX: 5M)
[--] Reads / Writes: 82% / 18%
[--] Total buffers: 192.0M global + 2.7M per thread (151 max threads)
[!!] Maximum possible memory usage: 597.8M (121% of installed RAM)
-------- Recommendations -----------------------------------------------------
General recommendations:
    ...
    Reduce your overall MySQL memory footprint for system stability
    ...

Eso de que el máximo de RAM que puede consumir MySQL es del 121% de la RAM instalada no me ha gustado (y a mysqltuner.pl tampoco). ¿Qué hacer para corregirlo? Lo veremos en otro post…

Acceso a MySQL remoto vía Android y SSH tunneling

Otra receta, esta vez para poder acceder desde nuestro dispositivo Android a una DB MySQL remota protegida por un firewall que impide la conexión directa. Necesitaremos realizar 3 pasos:

1) Instalar Connect Bot (para la parte SSH que explicaré a continuación) y MySQL Connect (de Javier Romero).

2) Generar un túnel SSH que permita conectar el puerto 3306 del dispositivo Android al puerto 3306 de la máquina remota (vía túnel SSH, porque el puerto 3306 remoto, recuerda, está filtrado por el firewall)

Para ello, en Connect Bot mantenemos pulsada la conexión SSH que queremos tunelizar y en el menú contextual elegimos «Editar redirección de puertos». Ahí configuramos una nueva redirección así: (la traducción del primer campo está mal, debería poner ‘nombre del túnel’ o algo similar, no nombre del usuario)

Conectamos ahora normalmente con Connect Bot (como si de una conexión SSH normal se tratara). Internamente estará abriendo el túnel.

3) Abrir una conexión con protocolo MySQL desde el cliente Android (la aplicación que haga esto en principio no sabe que el puerto 3306 local es realmente un extremo del túnel SSH. Para la aplicación Android ese puerto corresponde a una BD MySQL local!) En la imagen adjunta, «tester» es el nombre de usuario MySQL que tengas configurado en la DB remota.

¡Listo! Ya puedes ver y editar tuplas y esquemas de tus tablas cómodamente desde tu tablet Android (desde tu móvil también, pero no tan cómodamente 😉

Copiar bases de datos en MySQL

Así que quieres copiar una base de datos de un servidor en otro… bien, nada más facil si tu SGBD resulta que es MySQL.

$ mysqldbcopy --source=login:pass@localhost:3306 --destination=login:pass@localhost:3306 dborigen:dbdestino

El comando mysqldbcopy forma parte de las utilidades de línea de comandos de MySQL Workbench. Puedes obtener la lista completa de comandos disponibles, así como sus páginas man, en la página oficial de ayuda de MySQL Utilities