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 importantes. No hace mucho tiempo, en uno de nuestros proyectos, era hora 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 una operación similar 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é relacionada con la migración de la base de datos: cambios en los requisitos para los límites de los recursos del sistema y la corrección de las configuraciones de la base de datos, que deben eliminarse de las directivas obsoletas.

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


Y haz un plan de acción:

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

Analizaremos cada elemento del plan y veremos qué puede salir mal.

¡IMPORTANTE! El procedimiento de actualización del clúster MySQL basado en Galera tiene sus propias sutilezas que no se describen en el artículo. No debe usar estas instrucciones en este caso.

Parte 1: Verificación de configuraciones


En la versión 8, MySQL fue eliminado query_cache. De hecho, se declaró obsoleto en la versión 5.7, pero ahora está completamente eliminado . En consecuencia, es necesario eliminar las directivas relacionadas. Y para el almacenamiento en caché de consultas, ahora puede usar herramientas externas, por ejemplo, ProxySQL .

También se encontraron directivas pro obsoletas en la configuración innodb_file_format. Si en MySQL 5.7 fue posible seleccionar el formato InnoDB, entonces la octava versión ya funciona solo con el formato Barracuda .

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

  • query_cache_type, query_cache_limitY query_cache_size;
  • innodb_file_formaty innodb_file_format_max.

Para la verificación, utilizaremos la imagen Docker del servidor Percona. Pondremos la configuración del servidor en el directorio mysql_config_testy luego crearemos los 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

Resultado: en los registros de Docker o en el directorio con los registros, según sus configuraciones, aparecerá un archivo en el que se describirán las directivas del problema.

Aquí está 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, aún teníamos que lidiar con las codificaciones y reemplazar la directiva obsoleta expire-logs-days.

Parte 2: Verificación de instalaciones en ejecución


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

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

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

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



además, la utilidad mysql-shell está disponible en versiones modernas de MySQL (en el caso de Percona, este es un paquete percona-mysql-shell). Es un reemplazo para el cliente mysql clásico y combina las funciones del cliente, el editor SQL y las herramientas de administración 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

Y aquí están los comentarios que recibimos:



en general, nada crítico, solo advertencias sobre codificaciones (ver más abajo) . El resultado general de la implementación:



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

Una nota sobre las advertencias anteriores que indican problemas de codificación. El hecho es que UTF-8 en MySQL hasta hace poco no era un UTF-8 "real" , ya que solo almacenaba 3 bytes en lugar de 4. En MySQL 8, finalmente decidieron arreglarlo : el alias utf8pronto conducirá a la codificación utf8mb4, y los antiguos las columnas en las tablas se convertirán utf8mb3. En el futuro, la codificación utf8mb3se eliminará, pero no en esta versión. Por lo tanto, decidimos arreglar las codificaciones que ya están en una instalación funcional del DBMS, después de actualizarlo.

Parte 3: actualizaciones del servidor


¿Qué puede salir mal cuando hay un plan tan elegante? ... Sabiendo que los matices siempre ocurren, realizamos el primer experimento en el MySQL Dev-Cluster.

Como ya se mencionó, la documentación oficial destaca el problema de actualizar los servidores MySQL con réplicas. La conclusión es que al principio vale la pena actualizar todas las réplicas (esclavas), ya que MySQL 8 puede replicar desde el asistente de la versión 5.7. Alguna dificultad radica en el hecho de que usamos el modo maestro <-> maestro cuando el maestro remoto está en modo de solo lectura . Es decir, de hecho, el tráfico de combate ingresa a un centro de datos, y el segundo es el respaldo.

La topología es la siguiente: la



actualización debe comenzar con las réplicas mysql replica dc 2, mysql master dc 2 y mysql replica dc 1, y terminando con el servidor mysql master dc 1. Para una mayor confiabilidad, detuvimos las máquinas virtuales, las hicimos instantáneas y detuvimos la replicación con el comando justo antes de la actualización STOP SLAVE. El resto de la actualización se ve así:

  1. Cada réplica de reinicio, añadiendo la opción de configuración 3: skip-networking, skip-slave-start, skip-log-bin. El hecho es que la actualización de la base de datos genera registros binarios con la actualización 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 entrará en los registros binarios. Esto evitará problemas al reanudar la replicación.
  2. Instala el paquete percona-server-server. Es importante tener en cuenta que en MySQL 8, no necesita ejecutar el comando mysqlupgradedespués de actualizar el servidor.
  3. Después de un inicio exitoso, reinicie el servidor nuevamente, ya sin los parámetros que se agregaron en el primer párrafo.
  4. Nos aseguramos de que la replicación funcione correctamente: verificamos SHOW SLAVE STATUSy vemos que las tablas con contadores en la base de datos de la aplicación estén actualizadas.

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

No hubo tristeza - actualizamos productos


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

Afortunadamente, el proceso de actualización en sí comienza con las réplicas, por lo tanto, al encontrar dificultades, detuvimos el trabajo y restauramos la réplica de la instantánea. El estudio del problema fue reprogramado a la mañana siguiente. Las siguientes entradas aparecieron en los registros:

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

Un estudio de los archivos de varias listas de correo en Google llevó a la comprensión de que tal problema surge debido a un error de MySQL . Aunque más bien es incluso un error de utilidad mysqlchecky mysqlsh.

Resulta que MySQL ha cambiado la forma en que se presentan los datos para los campos decimales (int, tinyint, etc.), por lo que se usa otra forma de almacenarlos dentro de mysql-server. Si su base de datos estaba originalmente en la versión 5.5 o 5.1, y luego actualizó a 5.7, es posible que deba producir OPTIMIZEalgunas tablas. Luego MySQL actualizará los archivos de datos, transfiriéndolos al formato de almacenamiento actual.

También puede verificar 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_typetiene 0, el tipo anterior se usa en la tabla; debe hacerse OPTIMIZE. Sin embargo, si el valor es 246, ya tiene un nuevo tipo. Se puede encontrar más información sobre los tipos en el código .

Además, este error considera la segunda razón posible que nos ha pasado por alto: la falta 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 durante la actualización, puede usar el script SQL adjunto .

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

Desafortunadamente, en una base de datos grande que realmente funcione, no funcionará solo para tomar y realizar la ubicua OPTIMIZE. Percona-toolkit ayudará aquí: la utilidad pt-online-schema-change es excelente para la operación OPTIMIZE en línea.

El plan actualizado fue el siguiente:

  1. Optimizar todas las tablas.
  2. Realizar una actualización de la base de datos.

Para verificarlo y al mismo tiempo averiguar el tiempo de actualización, deshabilitamos una de las réplicas y para todas las tablas ejecutamos el siguiente comando:

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 bloqueos largos debido al hecho de que la utilidad crea una nueva tabla temporal en la que copia los datos de la tabla principal. En el momento en que ambas tablas son idénticas, la tabla original se bloquea y se reemplaza por una nueva. En nuestro caso, una ejecución de prueba mostró que la actualización de todas las tablas llevaría aproximadamente un día, pero copiar los datos causó demasiada carga en los discos.

Para evitar esto, en producción agregamos un argumento --sleepcon un valor de 10 al comando : este parámetro controla la duración de la espera después de transferir un paquete de datos a una nueva tabla. De esta forma, puede reducir la carga si una aplicación realmente en ejecución requiere 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 funcionó muy extraño: periódicamente, comenzaron las caídas de conexión . Esto es lo que parecía en el monitoreo:



el gráfico de diente de sierra es visible en la captura de pantalla, debido al hecho de que parte de los hilos del servidor MySQL se caía periódicamente con un error. Errores aparecieron en la aplicación:

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

Una inspección rápida de los registros reveló que el demonio mysqld no podía obtener los recursos necesarios del sistema operativo. Al tratar con los errores, encontramos en el sistema archivos de política de apariencia "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 formaron durante la actualización a MySQL 5.7 hace un par de años y pertenecen al paquete remoto. Eliminar 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

Finalmente


Cualquiera, incluso la operación más simple, puede conducir a problemas inesperados. E incluso tener un plan bien pensado no siempre garantiza el resultado esperado. Ahora, en cualquier plan de actualización, nuestro equipo también incluye la limpieza obligatoria de archivos adicionales que podrían aparecer como resultado de acciones recientes.

¡Y con este trabajo gráfico no tan profesional, me gustaría agradecer a Percona por sus excelentes productos!



PD


Lea también en nuestro blog:


All Articles