Actualización de MySQL (Servidor Percona) de 5.7 a 8.0

Actualización de MySQL (Servidor Percona) de 5.7 a 8.0

El progreso no se detiene, por lo que las razones para actualizar a las últimas versiones de MySQL son cada vez más convincentes. No hace mucho, en uno de nuestros proyectos, llegó el momento de actualizar los acogedores clústeres de Percona Server 5.7 a la versión 8. Todo esto sucedió en la plataforma Ubuntu Linux 16.04. Cómo realizar dicha operación con un tiempo de inactividad mínimo y qué problemas encontramos durante la actualización: lea este artículo.

Formación

Cualquier actualización del servidor de la base de datos probablemente esté asociada con la reconfiguración de la base de datos: cambios en los requisitos para los límites de los recursos del sistema y corrección de las configuraciones de la base de datos que deben eliminarse de directivas obsoletas.

Antes de actualizar, definitivamente nos referiremos a la documentación oficial:

Y elaboremos un plan de acción:

  1. Corrija los archivos de configuración eliminando directivas obsoletas.
  2. Comprueba la compatibilidad con las utilidades.
  3. Actualice las bases de datos esclavas instalando el paquete percona-server-server.
  4. Actualice el maestro con el mismo paquete.

Analicemos cada punto del plan y veamos qué podría salir mal.

IMPORTANTE! El procedimiento para actualizar un clúster MySQL basado en Galera tiene sus propias sutilezas que no se describen en el artículo. No debe utilizar esta instrucción en este caso.

Parte 1: verificar configuraciones

MySQL fue eliminado en la versión 8 query_cache. En realidad el era declarado obsoleto de nuevo en la versión 5.7, pero ahora completamente eliminado. En consecuencia, es necesario eliminar las directivas asociadas. Y para almacenar en caché las solicitudes, ahora puede utilizar herramientas externas, por ejemplo, proxysql.

También en la configuración había directivas obsoletas sobre innodb_file_format. Si en MySQL 5.7 era posible seleccionar el formato InnoDB, entonces la octava versión ya funciona sólo con formato Barracuda.

Nuestro resultado es la eliminación de las siguientes directivas:

  • query_cache_type, query_cache_limit и query_cache_size;
  • innodb_file_format и innodb_file_format_max.

Para comprobarlo, usaremos la imagen Docker de Percona Server. Colocaremos la configuración del servidor en el directorio. mysql_config_test, y junto a él crearemos directorios para datos y registros. Ejemplo de prueba de configuración del servidor Percona:

mkdir -p {mysql_config_test,mysql_data,mysql_logs}
cp -r /etc/mysql/conf.d/* mysql_config_test/
docker run  --name some-percona -v $(pwd)/mysql_config_test:/etc/my.cnf.d/  -v $(pwd)/mysql_data/:/var/lib/mysql/ -v $(pwd)/mysql_logs/:/var/log/mysql/ -e MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD} -d percona:8-centos

En pocas palabras: ya sea en los registros de Docker o en el directorio con los registros, dependiendo de sus configuraciones, aparecerá un archivo en el que se describirán las directivas problemáticas.

Esto es lo que teníamos:

2020-04-03T12:44:19.670831Z 0 [Warning] [MY-011068] [Server] The syntax 'expire-logs-days' is deprecated and will be removed in a future release. Please use binlog_expire_logs_seconds instead.
2020-04-03T12:44:19.671678Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.
2020-04-03T12:44:19.671682Z 0 [Warning] [MY-013244] [Server] --collation-server: 'utf8_general_ci' is a collation of the deprecated character set UTF8MB3. Please consider using UTF8MB4 with an appropriate collation instead.

Por lo tanto, todavía necesitábamos descubrir las codificaciones y reemplazar la directiva obsoleta. expire-logs-days.

Parte 2: Comprobación de instalaciones en funcionamiento.

La documentación de actualización contiene 2 utilidades para verificar la compatibilidad de la base de datos. Su uso ayuda al administrador a comprobar la compatibilidad de la estructura de datos existente.

Comencemos con la utilidad clásica mysqlcheck. Simplemente ejecuta:

mysqlcheck -u root -p --all-databases --check-upgrade

Si no se encuentran problemas, la utilidad saldrá con el código 0:

Actualización de MySQL (Servidor Percona) de 5.7 a 8.0

Además, hay una utilidad disponible en las versiones modernas de MySQL. mysql-shell (en el caso de Percona este es el paquete percona-mysql-shell). Es un reemplazo del clásico cliente mysql y combina las funciones de un cliente, un editor de código SQL y herramientas de administración de MySQL. Para verificar el servidor antes de actualizar, puede ejecutar los siguientes comandos a través de él:

mysqlsh -- util check-for-server-upgrade { --user=root --host=1.1.1.1 --port=3306 } --config-path=/etc/mysql/my.cnf

Aquí están los comentarios que recibimos:

Actualización de MySQL (Servidor Percona) de 5.7 a 8.0

En general, nada crítico: solo advertencias sobre codificaciones. (vea abajo). Resultado general de la ejecución:

Actualización de MySQL (Servidor Percona) de 5.7 a 8.0

Decidimos que la actualización debería realizarse sin problemas.

Una nota sobre las advertencias anteriores que indican problemas con las codificaciones. El hecho es que UTF-8 en MySQL hasta hace poco no era "verdadero" UTF-8, ya que almacenó sólo 3 bytes en lugar de 4. En MySQL 8 esto finalmente es decidió arreglarlo: alias utf8 pronto conducirá a la codificación utf8mb4, y las antiguas columnas de las tablas se convertirán en utf8mb3. Codificación adicional utf8mb3 se eliminará, pero no en esta versión. Por lo tanto, decidimos corregir las codificaciones que ya están en la instalación del DBMS en ejecución, después de actualizarlo.

Parte 3: Actualizaciones del servidor

¿Qué podría salir mal cuando existe un plan tan inteligente? Entendiendo perfectamente que siempre ocurren matices, realizamos el primer experimento en un clúster de desarrollo MySQL.

Como ya fue mencionado, documentación oficial Cubre el tema de la actualización de servidores MySQL con réplicas. La conclusión es que primero debe actualizar todas las réplicas (esclavas), ya que MySQL 8 puede replicar desde una versión maestra 5.7. Alguna dificultad radica en el hecho de que utilizamos el modo. maestro <-> maestro, cuando el maestro remoto está en modo sólo lectura. Es decir, de hecho, el tráfico de combate va a un centro de datos y el segundo es uno de respaldo.

La topología se ve así:

Actualización de MySQL (Servidor Percona) de 5.7 a 8.0

La actualización debe comenzar con réplicas. réplica de mysql dc 2, maestro mysql dc 2 и mysql replica dc 1y terminamos con el servidor mysql master dc 1. Para ser más confiables, detuvimos las máquinas virtuales, tomamos instantáneas de ellas e inmediatamente antes de la actualización detuvimos la replicación con el comando STOP SLAVE. El resto de la actualización se ve así:

  1. Reiniciamos cada réplica agregando 3 opciones a las configuraciones: skip-networking, skip-slave-start, skip-log-bin. El hecho es que la actualización de la base de datos genera registros binarios con actualizaciones de las tablas del sistema. Estas directivas garantizan que no habrá cambios en los datos de la aplicación en la base de datos y que la información sobre la actualización de las tablas del sistema no se incluirá en los registros binarios. Esto evitará problemas al reanudar la replicación.
  2. Instalación del paquete percona-server-server. Es importante tener en cuenta que en MySQL versión 8 no necesitas ejecutar el comando mysqlupgrade después de la actualización del servidor.
  3. Después de un inicio exitoso, reiniciamos el servidor nuevamente, sin los parámetros agregados en el primer párrafo.
  4. Nos aseguramos de que la replicación funcione correctamente: verifique SHOW SLAVE STATUS y ver que las tablas con contadores en la base de datos de la aplicación estén actualizadas.

Todo parece bastante simple: la actualización del desarrollador fue exitosa. Ok, puedes programar de forma segura una actualización nocturna para producción.

No hubo tristeza: actualizamos el producto.

Sin embargo, la transferencia de la exitosa experiencia de desarrollo a producción no estuvo exenta de sorpresas.

Afortunadamente, el proceso de actualización en sí comienza con las réplicas, por lo que cuando encontramos dificultades, detuvimos el trabajo y restauramos la réplica desde la instantánea. La investigación de los problemas se pospuso hasta la mañana siguiente. Los registros contenían las siguientes entradas:

2020-01-14T21:43:21.500563Z 2 [ERROR] [MY-012069] [InnoDB] table: t1 has 19 columns but InnoDB dictionary has 20 columns
2020-01-14T21:43:21.500722Z 2 [ERROR] [MY-010767] [Server] Error in fixing SE data for db1.t1
2020-01-14T21:43:24.208365Z 0 [ERROR] [MY-010022] [Server] Failed to Populate DD tables.
2020-01-14T21:43:24.208658Z 0 [ERROR] [MY-010119] [Server] Aborting

La investigación de los archivos de varias listas de correo en Google nos llevó a comprender que este problema se debe a Error de MySQL. Aunque es más probable que se trate de un error de utilidad. mysqlcheck и mysqlsh.

Resulta que MySQL cambió la forma en que representan los datos de los campos decimales (int, tinyint, etc.), por lo que mysql-server usa una forma diferente de almacenarlos. Si su base de datos inicialmente estaba en la versión 5.5 o 5.1, y luego actualizó a 5.7, entonces es posible que deba hacer OPTIMIZE para algunas mesas. Luego MySQL actualizará los archivos de datos y los transferirá al formato de almacenamiento actual.

También puedes comprobar esto con la utilidad. mysqlfrm:

mysqlfrm --diagnostic -vv /var/lib/mysql/db/table.frm
...
 'field_length': 8,
  'field_type': 246, # формат поля
  'field_type_name': 'decimal',
  'flags': 3,
  'flags_extra': 67,
  'interval_nr': 0,
 'name': 'you_deciaml_column',
...

si field_type Si lo tiene igual a 0, entonces en la tabla se usa el tipo antiguo; debe realizar OPTIMIZE. Sin embargo, si el valor es 246, ya tienes un nuevo tipo. Puede encontrar más información sobre los tipos en código.

Además, en este error Estamos considerando la segunda posible razón que se nos pasó por alto: la ausencia de tablas InnoDB en la tabla del sistema. INNODB_SYS_TABLESPACES, si ellas, tablas, se crearon en la versión 5.1. Para evitar problemas al actualizar, puedes utilizar script SQL adjunto.

¿Por qué no tuvimos tales problemas en desarrollo? La base de datos se copia allí periódicamente desde la producción, por lo que se recrean las tablas.

Desafortunadamente, en una base de datos grande que realmente funcione, no podrás simplemente tomar y ejecutar una base de datos universal. OPTIMIZE. percona-toolkit ayudará aquí: la utilidad pt-online-schema-change es excelente para la operación OPTIMIZAR en línea.

El plan actualizado tenía este aspecto:

  1. Optimice todas las tablas.
  2. Actualizar las bases de datos.

Para comprobarlo y al mismo tiempo conocer la hora de actualización, desactivamos una de las réplicas y ejecutamos el siguiente comando para todas las tablas:

pt-online-schema-change --critical-load Threads_running=150 --alter "ENGINE=InnoDB" --execute --chunk-size 100 --quiet --alter-foreign-keys-method auto h=127.0.0.1,u=root,p=${MYSQL_PASSWORD},D=db1,t=t1

Las tablas se actualizan sin largos bloqueos debido a que la utilidad crea una nueva tabla temporal en la que copia datos de la tabla principal. En el momento en que ambas tablas son idénticas, la tabla original se bloquea y se reemplaza por la nueva. En nuestro caso, una ejecución de prueba mostró que se necesitaría aproximadamente un día para actualizar todas las tablas, pero copiar datos provocó demasiada carga en los discos.

Para evitar esto, en producción agregamos el argumento al comando --sleep con un valor de 10: este parámetro ajusta la duración de la espera después de transferir un lote de datos a una nueva tabla. De esta manera puede reducir la carga si la aplicación en ejecución exige mucho tiempo de respuesta.

Después de realizar la optimización, la actualización fue exitosa.

... ¡pero no del todo!

Media hora después de la actualización, el cliente tuvo un problema. La base de datos funcionó de manera muy extraña: periódicamente comenzaban se restablece la conexión. Así se veía en el seguimiento:

Actualización de MySQL (Servidor Percona) de 5.7 a 8.0

La captura de pantalla muestra un gráfico en forma de diente de sierra debido al hecho de que algunos de los subprocesos del servidor MySQL fallaban periódicamente con un error. Aparecieron errores en la aplicación:

[PDOException] SQLSTATE[HY000] [2002] Connection refused

Una inspección rápida de los registros reveló que el demonio mysqld no pudo obtener los recursos necesarios del sistema operativo. Mientras solucionábamos errores, descubrimos en el sistema. Archivos de políticas de apparmor "huérfanos":

# dpkg -S /etc/apparmor.d/cache/usr.sbin.mysqld
dpkg-query: no path found matching pattern /etc/apparmor.d/cache/usr.sbin.mysqld
# dpkg -S /etc/apparmor.d/local/usr.sbin.mysqld
dpkg-query: no path found matching pattern /etc/apparmor.d/local/usr.sbin.mysqld
# dpkg -S /etc/apparmor.d/usr.sbin.mysqld
mysql-server-5.7: /etc/apparmor.d/usr.sbin.mysqld
# dpkg -l mysql-server-5.7
rc  mysql-server-5.7 5.7.23-0ubuntu0.16.04.1      amd64

Estos archivos se crearon al actualizar a MySQL 5.7 hace un par de años y pertenecen a un paquete eliminado. Eliminar los archivos y reiniciar el servicio apparmor resolvió el problema:

systemctl stop apparmor
rm /etc/apparmor.d/cache/usr.sbin.mysqld
rm /etc/apparmor.d/local/usr.sbin.mysqld
rm /etc/apparmor.d/usr.sbin.mysqld
systemctl start apparmor

en conclusión

Cualquier operación, incluso la más sencilla, puede provocar problemas inesperados. E incluso tener un plan bien pensado no siempre garantiza el resultado esperado. Ahora, cualquier plan de actualización que tenga nuestro equipo también incluye la limpieza obligatoria de archivos innecesarios que podrían haber aparecido como resultado de acciones recientes.

Y con esta creatividad gráfica poco profesional, ¡me gustaría agradecer enormemente a Percona por sus excelentes productos!

Actualización de MySQL (Servidor Percona) de 5.7 a 8.0

PS

Lea también en nuestro blog:

Fuente: habr.com

Añadir un comentario