MySQL Query Log

Introducción

En ocasiones queremos depurar qué consulta se ejecuta de forma efectiva en la base de datos (por ejemplo al usar consultas preparadas o un ORM) y la forma de hacer cuando usamos como SGBD MySQL es activar el General Query Log.

Este Log es un registro de las consultas que va ejecutando el servidor MySQL. Además, hay que tener presente que este log se debe activar sólo cuando estamos depurando una funcionalidad puntual pues en servidores muy activos puede crecer hasta alcanzar un gran tamaño.

Uso de General Query Log

Lo primero es editar el firchero my.cnf  (o my.ini en windows) y buscar la sección [mysqld]. En ella pondremos las opciones:

general_log_file = /path/to/query.log
general_log      = 1

Tras reiniciar el servidor mysql, podemos abrir el fichero de log y ejecutar varias consultas:

$ mysql -uroot mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 212
Server version: 5.7.21 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> select User, Host from user;
+---------------+-----------+
| User          | Host      |
+---------------+-----------+
| tienda        | %         |
| mysql.session | localhost |
| mysql.sys     | localhost |
| root          | localhost |
+---------------+-----------+
4 rows in set (0.00 sec)

El fichero de log generado por el servidor contiene:


wampmysqld, Version: 5.7.21-log (MySQL Community Server (GPL)). started with:
TCP Port: 3306, Named Pipe: /tmp/mysql.sock
Time                 Id Command    Argument
2018-11-20T10:55:09.930402Z	    2 Connect	root@localhost on mysql using TCP/IP
2018-11-20T10:55:09.934477Z	    2 Query	select @@version_comment limit 1
2018-11-20T10:55:20.218671Z	    2 Query	select User, Host from user
2018-11-20T10:55:21.721707Z	    2 Quit	

Y estas son las sentencias que se ejecutan en MySQL.

Referencias

Importar/exportar datos en MySQL

Introducción

Tenemos una tabla marcas como la siguiente, ¿cómo podemos exportarla?

SELECT * FROM `marcas`

id_marca nombre       url  avatar 
1        Zara         NULL NULL 
2        Woman Secret NULL NULL 
3        New Look     NULL NULL

Soluciones

Exportar con mysqldump

$ mysqldump -ubasedatos -pcontraseña --extended-insert=false --hex-blob nombrebasededatos > volcado.sql

Exportar con SELECT … INTO OUTFILE

Opciones

[FIELDS
[TERMINATED BY '\t']
[[OPTIONALLY] ENCLOSED BY '']
[ESCAPED BY '\\' ]
]
[LINES
[STARTING BY '']
[TERMINATED BY '\n']
]

Ejemplo:

SELECT * INTO OUTFILE '/path/to/result.txt'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM marcas;

Importar fichero SQL

$ mysql -ubasedatos -pcontraseña nombrebasededatos < volcado.sql

Importar datos con LOAD DATA INFILE

LOAD DATA sirve para tomar cualquier archivo “comma-separated” (separado por comas, aunque no necesariamente son comas) y cargarlo como datos en alguna tabla de MySQL.Un ejemplo para recuperar los datos anteriores:

LOAD DATA LOCAL INFILE '/path/to/result.txt'
INTO TABLE marcas
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n' (id_marca, nombre, url, avatar );

Referencias

  1. https://phenobarbital.wordpress.com/2007/08/03/cargar-datos-en-mysql-con-load-data-infile/
  2. https://dev.mysql.com/doc/refman/5.1/en/load-data.html
  3. https://dev.mysql.com/doc/refman/5.1/en/mysqldump.html
  4. https://dev.mysql.com/doc/refman/5.1/en/select-into.html

Modificar puerto HTTP para Oracle XE

Problema

Cuando se instala el SGBD Oracle XE para desarrollo en un entorno local se instala con un servidor de aplicaciones desplegado en el puerto 8080. Este comportamiento es muy molesto cuando queremos usar un servidor tomcat o desplegar aplicaciones spring boot.

Pero es muy sencillo de arreglar, basta abrir una sesión en sqlplus y ejectuar el comando (EXEC DBMS_XDB.SETHTTPPORT(numero_puerto)):

$ sqplus system/XE

SQL*Plus ...
SQL> Exec DBMS_XDB.SETHTTPPORT(9090);
PL/SQL procedure sucessfully completed.

OJO: si queremos deshabilitar el servidor:

EXEC DBMS_XDB.SETHTTPPORT(0)

Referencias:

Referencias vistas el 24 de sep de 2018:

Audit Log con Entity Framework (.NET)

Introducción

Cuando desarrollamos aplicaciones de una cierta envergadura debemos de plantearnos usar ciertos patrones de diseño que garantizen la escalabilidad, robustez,  tolerancia a fallos y auditen nuestra aplicación.

Vamos a ver cómo usar el patrón Audit Log para auditar los eventos y operaciones de la aplicación.

Un audit log es un registro de las acciones que ocurren sobre una aplicación con unos datos (una entidad, una colección, un VO, …) y registra cuando ocurre una operación, quien ha sido el responsable, qué operación ha realizado y se puede incluir la información modificada (en su estado inicial y el modificado).

Para leer más sobre audit log leer el enlace adjunto de Martin Fowler.

Otro de los problemas cubiertos en esta entrada es cómo obtener el nombre de la tabla / vista de una entidad en entity framework.

Caso

Supongamos que tenemos una tabla PRODUCTOS sobre un SGBD Oracle y hemos desarrollado una aplicación basada en microservicios con .NET. Además hemos decidido utilizar el ORM Entity Framework como capa de abstracción para el acceso a datos.

Problemas que se presentan:

  • Cómo usamos un ORM contra un SGB, ¿cómo obtener el nombre de la tabla?
  • ¿Cómo implemento el audit log

Solución

Obtener el nombre de la tabla en EF

En Entity Framework, al definir una clase como una entidad de base de datos se anota con el decorador Table para indicar la tabla de base de datos (sino se llama igual que la clase), por ejemplo:

[Table("PRODUCTOS", Schema = "MI_BASE_DE_DATOS")]
public partial class Producto
{
    [Key]
    public int Id { get; set; }
    [StringLength(100)]
    public string Nombre { get; set; }
    ...
}

Esta clase representa nuestro producto mapeado em la base de datos. Al ser una entidad, si hacesmos un ToString() sobre su tipo, obtenemos el SQL que infiere Entity Framework para realizar consultas:

Set(typeof(Producto)).ToString()

Generando el siguiente SQL:

SELECT
“Extent1″.”Id” AS “Id”,
“Extent1″.”Nombre” AS “Nombre”,

FROM “MI_BASE_DE_DATOS”.”PRODUCTOS” “Extent1”

Con lo que podemos implementar una función de utilidad para obtener el nombre de la tabla para cada entidad:

public string GetTableName(Type entityType, bool debug = false)
{
  string sql = Set(entityType).ToString();
  if (debug)
    Console.WriteLine("La consulta SQL es: {0}", sql);
  Regex regex = new Regex(@"FROM\s+(?<table>.+)\s+");
  return regex.Match(sql).Groups["table"].Value;
}

Implementación sencilla del auditlog

Para implementar el auditlog hay que tener en cuenta una cuestión, ¿qué sistema de loggijng usamos? Log4net, uno propio, mongodb, elasticsearch, stdout … Vamos a hacer un sencillo ejemplo con stdout (modificar el ejemplo es llamar a nuestro servicio de logging).

public void auditLog(int userid, string operation, string table, string message = null)
{
  Console.WriteLine(string.Format(LOG, DateTime.Now, userid, operation, table, message));
}

LOG es una constante de cadena con el formato de la línea de log, por ejemplo:

const string LOG = “{0} – UserId = {1:D6} [{3} – {2}] – {4}”;

Cuya salida podría ser:

05/11/2018 12:50:18 – UserId = 012345 [“MI_BASE_DE_DATOS”.”PRODUCTOS” – DELETE] – Se ha borrado un registro

A partir de aquí, muchas opciones, soluciones y formas de adaptar el problema a una solución particular.

Referencias

Obtener contenido binario en un Select en Informix

Ver hexadecimal en Informix

En ocasiones resulta interesante poder ver el cotenido de un campo de base de datos en binario (o hexadecimal). Por ejemplo para tema de charsets, o por verificar la forma de almacenarlo.

En infromix tenemos una manera de hacerlo muy sencillo:

SELECT CAST(nombre_campo AS BYTE)
FROM nombre_tabla
WHERE expresion_condicion;

Un ejemplo de resultado:

(nombre_del_campo)                                        
----------------------------------------------------
af  61  6c  75  7a  6a  65  20  64  72  65  77  6e  
52  6f  6c  65  74  79  20  70  6c  65  63  69  6f

Espero que resulte útil.

Referencias

CAST Expressions: (visto 6 de julio de 2017) https://www.ibm.com/support/knowledgecenter/en/SSGU8G_12.1.0/com.ibm.sqls.doc/ids_sqs_0191.htm

Configurar proxy para Atom

Problema

En el trabajo usamos un proxy como en muchas grandes empresas. Uno de los diferentes editores que so es Atom (https://atom.io/). Y el problema es para instalar cualquier nueva características como un paquete, tema, etc.

Al acceder al gestor de paquetes (pulsar CTRL + COMA) y buscar un paquete no podremos instalarlo. En ese caso obtendremos el error:

tunneling socket could not be established, cause=connect ETIMEDOUT 192.169.35.2:3000

Solución

Para solucionarlo debemos configurar el gestor de paquetes de atom (APM) y esto sólo se puede hacer desde consola:

apm config set proxy "http://localhost:3128"
apm config set https_proxy proxy "http://localhost:3128"

Hecho esto, abrimos Atom y a trabajar:

Referencias

Deshabilitar ImprPant en Dropbox y habiitar en Greenshot

Greenshot es una herramienta muy útil para capturar la pantalla, zonas o ventanas en Windows.Pero cuando lo instalamos a la vez con Dropbox tenemos un problema con el uso de la tecla ImprPant.

El problema viene cuando YA está instalado Dropbox. Siguiendo los pasos de la ayuda de Dropbox encomtraremos cómo solucionarlo. Deshabilitamos el uso de la tecla Impr Pantalla de Dropbox y luego instalamos Greenshot para que éste use esa tecla como capturador estándar.

Organizar correos de Gmail por tamaño

Estoy organizando en mis ratos libres Gmail, porqué aunque Google ofrece mucho espacio es verdad que hay muchos correos con “basura” de la época en que se mandaba todo por email.

He encontrado la entrada muy útil con filtros para buscar en Gmail correos con ficheros adjuntos de un tamaño aproximado (alrededor de 15MB):

size:15mb

O ficheros con tamaños comprendidos entre:

larger_than:5m smaller_than:8M

A mi me ha sido muy útil.

Obtener vistas relacionadas en Oracle

Introducción

En ocasiones estamos manejado vistas o elementos de PL/SQL que necesitamos saber que relación existe entre ellos. Para esto oracle nos ofrece la vista user_dependencies que relaciona un objeto (vista, package, function, procedure) con otro si éste es dependencia de otro.

Caso de pruebas

Supongamos una vista ALUMNOS que se usa para hacer consulta, se consume en 1 procedure y 1 function. Si ejecutamos una consulta como la siguiente:


SELECT * FROM user_dependencies
  START WITH name = 'ALUMNOS'
  CONNECT BY PRIOR TRIM(referenced_name) = TRIM(name);

Obtendremos un resultado como el siguiente, donde veremos en la columna de la izquierda para cada ocurrencia de la izquierda en que elemento de la derecha esta como una dependencia.

Referencias

  1. USER_DEPENDENCIES:
    https://docs.oracle.com/cd/B28359_01/server.111/b28320/statviews_5252.htm
  2. ALL_DEPENDENCIES:
    https://docs.oracle.com/cd/B28359_01/server.111/b28320/statviews_1066.htm#i1576452

Desinstalar McAfee (Agent)

Introducción

Cuando compras un equipo nuevo de HP en ocasiones tienen la mala costumbre de traer software adicional instalado. En este caso el el antivirus McAfee VirusScan y su agente. Desinstalarlo no es fácil. No te permite hacerlo en una sesión normal y en modo a prueba de errores no se puede lanzar el servicio de Windows Installer. ¿Cómo hacerlo?

Desinstalar

En el enlace [1] se proporciona una forma de hacerlo (imagino que para equipos de 32 bits) en mi caso mi máquina es de 64 bits y viene instalado en la URL:

C:\Program Files\McAfee\Agent\x86

En esta carpeta abrimos una ventana de comandos (botón derecho + CTRL) y escribimos:

frminst.exe /remove=agent

Nos preguntará, contestamos que sí y a esperar que termine el prceso.

Referencia

  1. [BLOG de .josepros.com]: http://www.josepros.com/2010/02/desinstalacion-manual-de-mcafee.html