El alto uso de la CPU en una instancia puede deberse a varios motivos, como aumento en las cargas de trabajo, transacciones pesadas, consultas lentas y transacciones de ejecución prolongada.
El recomendador de instancias con aprovisionamiento insuficiente analiza el uso de la CPU. Si el nivel de uso de la CPU es igual o superior al 95 % durante un período considerable en los últimos 30 días, el recomendador le avisa y le proporciona información adicional para ayudarle a resolver el problema.
Este documento explica cómo revisar y optimizar una instancia de Cloud SQL para MySQL si el recomendador de instancias con aprovisionamiento insuficiente identifica que dicha instancia tiene un alto uso de CPU.
Recomendaciones
El uso de la CPU aumenta proporcionalmente con la carga de trabajo. Para reducirlo, revise las consultas en ejecución y optimícelas. A continuación, se indican algunos pasos para verificar el consumo de CPU.
Comprobar
Threads_running
yThreads_connected
Utilice la siguiente consulta para ver el número de subprocesos activos:
> SHOW STATUS like 'Threads_%';
Threads_running
es un subconjunto deThreads_connected
. El resto de los hilos están inactivos. Un aumento enThreads_running
contribuiría a un mayor uso de la CPU. Es recomendable comprobar qué se está ejecutando en esos hilos.Comprobar estados de consulta
Ejecute el comando
SHOW PROCESSLIST
para ver las consultas en curso. Devuelve todos los subprocesos conectados en orden y su instrucción SQL activa.mysql> SHOW [FULL] PROCESSLIST;
Preste atención a las columnas de estado y duración. Compruebe si hay varias consultas bloqueadas en el mismo estado.
- Si muchos subprocesos muestran
Updating
, podría haber una contención de bloqueo de registros. Consulte el siguiente paso. - Si muchos subprocesos muestran "
Waiting
bloqueo de metadatos de tabla", revise la consulta para identificar la tabla y luego busque un DDL (comoALTER TABLE
) que pueda contener el bloqueo de metadatos. Un DDL también podría estar esperando el bloqueo de metadatos de tabla si una consulta temprana, como unaSELECT query
de larga duración, lo contiene.
- Si muchos subprocesos muestran
Comprobar si hay contención de bloqueo de registros
Cuando las transacciones mantienen bloqueos en registros de índice populares, bloquean otras transacciones que solicitan los mismos bloqueos. Esto podría generar un efecto en cadena y provocar el bloqueo de varias solicitudes y un aumento en el valor de
Threads_running
. Para diagnosticar la contención de bloqueos, utilice la tablainformation_schema.innodb_lock_waits
.La siguiente consulta enumera cada transacción de bloqueo y la cantidad de transacciones bloqueadas asociadas.
SELECT t.trx_id, t.trx_state, t.trx_started, COUNT(distinct w.requesting_trx_id) AS blocked_trxs FROM information_schema.innodb_lock_waits w INNER JOIN information_schema.innodb_trx t ON t.trx_id = w.blocking_trx_id GROUP BY t.trx_id,t.trx_state, t.trx_started ORDER BY t.trx_id;
Tanto un único DML grande como muchos DML pequeños simultáneos pueden causar contenciones de bloqueo de filas. Puede optimizar esto desde la aplicación siguiendo estos pasos:
- Evite las transacciones largas porque los bloqueos de filas se mantienen hasta que finaliza la transacción.
- Divida un único DML grande en DML más pequeños.
- Divida un DML de una sola fila en fragmentos pequeños.
- Minimice la contención entre subprocesos; por ejemplo, si el código de la aplicación utiliza un grupo de conexiones, asigne un rango de ID al mismo subproceso.
Encuentra transacciones de larga duración
Utilice
SHOW ENGINE INNODB STATUS
En la sección TRANSACCIONES podrás ver todas las transacciones abiertas ordenadas de más antigua a más antigua.
mysql> SHOW ENGINE INNODB STATUS\G …… ------------ TRANSACTIONS ------------ … ---TRANSACTION 245762, ACTIVE 262 sec 2 lock struct(s), heap size 1136, 1 row lock(s), undo log entries 1 MySQL thread id 9210, OS thread handle 140262286128896, query id 202218 localhost root
Comience con las transacciones más antiguas y encuentre respuestas a las siguientes preguntas:
- ¿Cuánto tiempo llevan realizándose estas transacciones?
- ¿Cuántas estructuras de bloqueo y bloqueos de fila hay presentes?
- ¿Cuántas entradas de registro de deshacer hay?
- ¿Cuáles son los hosts y usuarios que se conectan?
- ¿Qué es la declaración SQL en curso?
Utilice
information_schema.innodb_trx
Si se truncó
SHOW ENGINE INNODB STATUS
, una forma alternativa de examinar todas las transacciones abiertas es utilizar la tablainformation_schema.innodb_trx
:SELECT trx_id, trx_state, timestampdiff(second, trx_started, now()) AS active_secs, timestampdiff(second, trx_wait_started, now()) AS wait_secs, trx_tables_in_use, trx_tables_locked, trx_lock_structs, trx_rows_locked, trx_rows_modified, trx_query FROM information_schema.innodb_trx
Si las transacciones muestran los extractos de larga duración actuales, puede decidir detenerlas para reducir la carga en el servidor o esperar a que se completen las transacciones críticas. Si las transacciones anteriores no muestran actividad, vaya al siguiente paso para consultar el historial de transacciones.
Comprobar las sentencias SQL de las transacciones de larga ejecución
Utilice
performance_schema
Para usar
performance_schema
, primero debe activarlo. Este cambio requiere reiniciar la instancia. Una vezperformance_schema
, compruebe que los instrumentos y consumidores estén habilitados:SELECT * FROM setup_consumers where name like 'events_statements_history'; SELECT * FROM setup_instruments where name like 'statement/sql/%';
Si no están habilitados, habilítelos:
UPDATE setup_instruments SET ENABLED = 'YES', timed = 'YES' WHERE NAME LIKE 'statement/%'; UPDATE setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE 'events_statements%';
De forma predeterminada, cada hilo conserva los últimos 10 eventos definidos por
performance_schema_events_statements_history_size
. Estos suelen ser suficientes para localizar la transacción en el código de la aplicación. Este parámetro no es dinámico.Con el
mysql thread id
, que esprocesslist_id
, consulta los eventos del historial:SELECT t.thread_id, event_name, sql_text, rows_affected, rows_examined, processlist_id, processlist_time, processlist_state FROM events_statements_history h INNER JOIN threads t ON h.thread_id = t.thread_id WHERE processlist_id = <mysql thread id> ORDER BY event_id;
Usar registro de consultas lentas
Para la depuración, puede capturar todas las consultas que tardaron más de
N
segundos en el registro de consultas lentas. Puede habilitar los registros de consultas lentas editando la configuración de la instancia en la página de instancias.Google Cloud consola ogcloud CLI
y luego vea los registros usando el visor de registros en elGoogle Cloud consola ogloud CLI
.
Comprobar la contención del semáforo
En un entorno concurrente, el mutex y el bloqueo de lectura/escritura en recursos compartidos pueden ser el punto de contención, lo que ralentiza el rendimiento del servidor. Además, si el tiempo de espera del semáforo supera los 600 segundos, el sistema puede colapsar para salir del bloqueo.
Para ver la contención del semáforo, utilice el siguiente comando:
mysql> SHOW ENGINE INNODB STATUS\G ---------- SEMAPHORES ---------- ... --Thread 140396021667584 has waited at row0purge.cc line 862 for 241.00 seconds the semaphore: S-lock on RW-latch at 0x30c03e8 created in file dict0dict.cc line 1183 a writer (thread id 140395996489472) has reserved it in mode exclusive number of readers 0, waiters flag 1, lock_word: 0 Last time read locked in file row0purge.cc line 862 Last time write locked in file /build/mysql-5.7-FFKPr6/mysql-5.7-5.7.22/storage/innobase/dict/dict0stats.cc line 2376 ...
Con cada espera de semáforo, la primera línea muestra el hilo en espera, el semáforo específico y el tiempo de espera. Si se producen esperas frecuentes al ejecutar repetidamente
SHOW ENGINE INNODB STATUS
, especialmente si superan unos pocos segundos, significa que el sistema está experimentando cuellos de botella de concurrencia.Hay diferentes puntos de contención en diferentes cargas de trabajo y configuraciones.
Cuando los semáforos suelen estar en btr0sea.c, la indexación hash adaptativa podría ser la fuente de contención. Intente desactivarla usando Google Cloud consola o
gcloud CLI
.Optimizar consultas
SELECT
largasPrimero, revise la consulta. Identifique el objetivo de la consulta y la mejor manera de obtener los resultados. El mejor plan de consulta es el que minimiza el acceso a los datos.
- Compruebe el plan de ejecución de la consulta:
mysql> EXPLAIN <the query>;
Consulte la documentación de MySQL para aprender a interpretar la salida y evaluar la eficiencia de la consulta.
- Utilice el índice correcto
Compruebe la columna clave para ver si se utiliza el índice esperado. De lo contrario, actualice las estadísticas del índice:
mysql> analyze table <table_name>
Aumente el número de páginas de muestra utilizadas para calcular las estadísticas de índice. Para obtener más información, consulte la documentación de MySQL .
- Aprovechar al máximo el índice
Al usar un índice multicolumna, revise las columnas
key_len
para ver si el índice se utiliza completamente para filtrar los registros. Las columnas más a la izquierda deben ser comparaciones de igualdad, y el índice puede usarse hasta la primera condición de rango, inclusive.- Utilice las sugerencias del optimizador
Otra forma de garantizar el índice correcto es utilizar la sugerencia de índice y la sugerencia para el orden de unión de la tabla .
Evite una lista de historial larga con READ COMMITTED
El historial es la lista de transacciones no purgadas en el espacio de tablas de deshacer. El nivel de aislamiento predeterminado de una transacción es
REPEATABLE READ
, que requiere que la transacción lea la misma instantánea durante toda su duración. Por lo tanto, una consultaSELECT
bloquea la purga de los registros de deshacer generados desde el inicio de la consulta (o transacción). Un historial extenso ralentiza el rendimiento de la consulta. Una forma de evitar generar un historial extenso es cambiar el nivel de aislamiento de la transacción aREAD COMMITTED
. ConREAD COMMITTED
, ya no es necesario mantener el historial para una vista de lectura consistente. Puede cambiar el nivel de aislamiento de la transacción globalmente para todas las sesiones, para una sola sesión o para la siguiente transacción. Para obtener más información, consulte la documentación de MySQL .Ajustar la configuración del servidor
Hay mucho que decir sobre la configuración del servidor. Si bien la historia completa queda fuera del alcance de este documento, cabe mencionar que el servidor también reporta diversas variables de estado que ofrecen indicios sobre el correcto funcionamiento de las configuraciones relacionadas. Por ejemplo:
- Ajuste
thread_cache_size
siThreads_created/Connections
es grande. Una caché de subprocesos adecuada reduciría el tiempo de creación de subprocesos y facilitaría la carga de trabajo con alta concurrencia. - Ajuste
table_open_cache
siTable_open_cache_misses/Table_open_cache_hits
no es trivial. Tener tablas en la caché de tablas ahorra tiempo de ejecución de consultas y podría marcar la diferencia en un entorno altamente concurrente.
- Ajuste
Finalizar una conexión no deseada
Puede detener la consulta si esta parece inválida o ya no es necesaria. Para saber cómo identificar y finalizar el hilo de MySQL, consulte Administrar conexiones de base de datos .
Por último, si el uso de la CPU sigue siendo alto y las consultas generan tráfico necesario, considere aumentar los recursos de la CPU en su instancia para evitar caídas o tiempos de inactividad de la base de datos.