Transação aberta por muito tempo Long-running transaction / MVCC purge lag
ID da causa db-long-tx · Responsável principal Desenvolvimento do servidor (Equipe de desenvolvimento) · Também envolvidos Infraestrutura de banco de dados (Equipe de infraestrutura)
Uma transação aberta por muito tempo continua segurando locks, e o BD não consegue limpar as versões antigas dos dados (purge), então tudo vai ficando mais lento.
Por quê Uma transação fica aberta enquanto espera a resposta de outro servidor, ou uma query de agregação longa roda no BD primário durante a operação → Efeito Os locks não são liberados, e as versões antigas que precisam ser limpas continuam se acumulando → Na tela Timeout nos recursos que usam aquela linha; ao longo de horas, salvamentos e consultas ficam lentos de modo geral
Quanto mais tempo ligado, Aleatoriamente, de vez em quando
Responsável
Responsável principal Desenvolvimento do servidor (Equipe de desenvolvimento) · Também envolvidos Infraestrutura de banco de dados (Equipe de infraestrutura)
O que fazer (Equipe de desenvolvimento)
Não esperar chamadas de rede nem input do usuário dentro de uma transação, rodar queries de agregação na réplica.
O que fazer (Equipe de infraestrutura)
Criar alerta para transações abertas por muito tempo e encerrá-las à força, oferecer uma réplica para agregações, monitorar o crescimento do undo log e das linhas mortas.
No gráfico
Subida lenta · Tamanho do undo log (History list length), linhas mortas
Onde olhar
No MySQL, achar a transação mais antiga pelo trx_started do INFORMATION_SCHEMA.INNODB_TRX e ver o History list length (undo log ainda não limpo) na seção TRANSACTIONS do SHOW ENGINE INNODB STATUS. No PostgreSQL, ver o xact_start e as sessões com state idle in transaction no pg_stat_activity, e o n_dead_tup no pg_stat_user_tables
Confirma se
Há uma transação aberta há minutos ou horas, e durante esse tempo o History list length ou o n_dead_tup sobem sem parar; depois que a transação termina e a limpeza (purge, VACUUM) roda, eles caem
Descarta se
Nenhuma transação antiga, mas tudo lento: mais provável, checkpoint (db-checkpoint) ou disco
Como verificar
Ferramentas de infra (sem precisar do código do jogo)
Saiba mais
O BD guarda versões antigas para que quem lê possa ver os dados como eram antes da alteração (MVCC). Esse histórico só pode ser apagado quando a transação mais antiga termina, então, se uma transação fica aberta por horas, acumula-se undo log no MySQL e linhas mortas (dead tuples) que o VACUUM não conseguiu limpar no PostgreSQL. No SQL Server, o log de transações não diminui e pode até encher o disco.
Fontes
InnoDB Multi-VersioningMySQL Enquanto houver transações que podem ver versões antigas, o undo log de update não pode ser descartado e o rollback segment cresce; recomenda-se fazer commit com frequência mesmo em transações só de leitura
Routine Vacuuming (PostgreSQL Documentation)PostgreSQL Versões antigas de linhas não podem ser apagadas enquanto outras transações puderem vê-las; transações abertas por muito tempo precisam ser finalizadas ou ter a sessão encerrada
Purge ConfigurationMySQL O purge limpa a lista de undo logs das transações confirmadas (history list); o volume pendente aparece como History list length na seção TRANSACTIONS do SHOW ENGINE INNODB STATUS