← Voltar ao blog

Indexers do Magento 2: Update on Save vs Update by Schedule

Rodrigo Biazzi

Todo indexer do Magento 2 roda em um de dois modos: Update on Save ou Update by Schedule. A escolha define se salvar um produto no admin também reconstrói os dados de índice na mesma requisição, ou se esse trabalho acontece depois, no cron. Num catálogo pequeno e com pouco tráfego a diferença quase não aparece. Numa loja de verdade, o modo errado causa saves lentos no admin, deadlocks durante importações ou dados do storefront horas desatualizados. Este artigo explica como os dois modos funcionam no Magento Open Source e no Adobe Commerce 2.4.8, como trocar e como manter o modo schedule saudável.

Por que o Magento precisa de indexers

O Magento guarda os dados do catálogo numa estrutura normalizada, com tabelas EAV por tipo de atributo, tabelas separadas para valores de website e store view e relações para categorias, inventário e preços. Ler o preço de um produto para um customer group num website a partir dessa estrutura exige muitos joins. Os indexers pré-calculam tabelas planas e fáceis de consultar, como relações de categoria e produto, preços finais por customer group, dados de busca e status de estoque. O storefront lê dessas tabelas de índice.

Quando os dados de origem mudam, as tabelas de índice precisam ser atualizadas. Os dois modos decidem quando.

Update on Save

No modo Update on Save, que a CLI chama de realtime, o indexer roda como parte do save. Quando um admin salva um produto, a mesma requisição atualiza as linhas afetadas nas tabelas de índice antes de responder.

A vantagem é que o storefront reflete a mudança na hora. As desvantagens crescem com o catálogo:

  • Os saves no admin ficam mais lentos, já que cada save também faz trabalho de índice para cada indexer afetado.
  • Ações em massa e importações disparam trabalho de índice para cada linha, o que pode transformar uma importação de dois minutos em uma hora.
  • Escritas de índice dentro da transação do save seguram locks por mais tempo. Com saves, importações e tráfego do storefront concorrentes, isso aumenta a chance de deadlocks e lock wait timeouts.

Update by Schedule

No modo Update by Schedule, chamado de schedule na CLI, o Magento usa o framework mview. Quando você muda um indexer para o modo schedule, o Magento cria triggers de banco nas tabelas de origem das quais aquele indexer depende. Cada insert, update ou delete nessas tabelas grava o ID da entidade numa tabela de changelog, com o nome da view mais o sufixo _cl, por exemplo catalog_product_price_cl.

O save em si só grava os dados de origem mais uma linha de changelog, o que é rápido. Depois, o job de cron indexer_update_all_views, no grupo de cron index, lê as novas entradas do changelog desde a última versão processada e reindexa só aquelas entidades. A versão atual de cada view é registrada na tabela mview_state.

A vantagem são saves e importações rápidos, menos locks e o trabalho de índice feito em lotes. A desvantagem é o atraso. Uma mudança aparece no storefront depois da próxima execução do cron de índice, em geral em um ou dois minutos se o cron roda a cada minuto e dá conta do recado.

Verificando e trocando os modos

bin/magento indexer:show-mode
bin/magento indexer:status

bin/magento indexer:set-mode schedule
bin/magento indexer:set-mode schedule catalog_product_price catalogsearch_fulltext
bin/magento indexer:set-mode realtime customer_grid

Sem os códigos de indexer, o set-mode vale para todos os indexers. Trocar para schedule cria os triggers e as tabelas de changelog. Voltar para realtime remove os triggers.

Criar triggers com binary logging ativo no MySQL exige o privilégio SUPER ou log_bin_trust_function_creators = 1. Se o set-mode schedule falhar com erro de privilégio, a causa é essa. O guia de tuning do MySQL cobre essa configuração.

Qual modo usar

Em lojas de produção, use Update by Schedule para quase tudo. É a configuração que a Adobe recomenda para produção e a que escala com o tamanho do catálogo e o tráfego.

A exceção comum é o indexer customer grid. Ele foi feito para reindexação completa e não suporta totalmente o modo schedule, então deixe o customer_grid em Update on Save. Assim o customer grid do admin é atualizado quando os customers são salvos.

Num ambiente local ou numa loja minúscula, Update on Save é cômodo porque você vê as mudanças na hora, sem cron. Só lembre que o comportamento local passa a ser diferente da produção, e bugs ligados a indexação atrasada não vão aparecer localmente.

O cron precisa rodar

O modo schedule só funciona se o cron roda, e especificamente o grupo index. Se o cron está quebrado, os triggers continuam gravando nas tabelas de changelog e nada as processa. As mudanças de produto nunca chegam ao storefront, e as tabelas de changelog crescem sem limite. Verifique:

SELECT * FROM mview_state;

SELECT COUNT(*) FROM catalog_product_price_cl;

SELECT job_code, status, scheduled_at, executed_at, finished_at
FROM cron_schedule
WHERE job_code LIKE 'indexer%'
ORDER BY scheduled_at DESC
LIMIT 20;

O version_id em mview_state deve acompanhar os IDs mais recentes nas tabelas de changelog. Se as linhas de cron mais novas dos jobs de indexer são antigas, ou se muitas estão presas em running ou error, conserte o cron primeiro. O guia de cron jobs explica como os grupos de cron funcionam e como rodar o grupo index separadamente.

Limpeza do changelog

As entradas de changelog já processadas são removidas pelo job de cron indexer_clean_all_changelogs. Enquanto o cron roda, as tabelas ficam pequenas. Se estiverem grandes, as entradas não estão sendo processadas ou não estão sendo limpas.

Indexers inválidos e reindexações completas

Um indexer fica inválido quando o Magento decide que o índice como um todo não é mais confiável, por exemplo depois de certas mudanças de configuração ou de atributos que afetam a estrutura do índice. O admin mostra uma mensagem, e o indexer:status mostra o indexer como precisando de reindex.

No modo schedule, o job de cron indexer_reindex_all_invalid reconstrói os indexers inválidos automaticamente. Você também pode rodar na mão:

bin/magento indexer:reindex catalog_product_price
bin/magento indexer:reset catalog_product_price

O indexer:reset marca um indexer como inválido, o que é útil quando você quer que o cron pegue aquele indexer para uma reconstrução completa. Evite rodar reindexações completas de indexers grandes em horário de pico. Elas pesam no banco e podem travar tabelas que o storefront lê.

Versões recentes do 2.4 também têm o bin/magento indexer:set-status, que pode definir um indexer como valid, invalid ou suspended. Suspender impede o cron de processar um indexer por um tempo, por exemplo durante uma importação grande que você vai seguir com uma reindexação completa. Confira bin/magento list indexer na sua instalação para confirmar os comandos disponíveis.

Dimensions do price indexer

O índice de preços de produto pode ser dividido por dimensions, de modo que cada combinação de website e customer group tenha sua própria tabela. Em lojas com muitos websites ou customer groups isso deixa o price indexer mais rápido e as tabelas menores:

bin/magento indexer:set-dimensions-mode catalog_product_price website_and_customer_group
bin/magento indexer:show-dimensions-mode

Mudar o modo de dimensions dispara uma reindexação completa dos preços. Planeje para um horário tranquilo.

Indexers customizados e mview

Se você escreve o seu próprio indexer, declara as subscriptions de mview em etc/mview.xml, listando quais tabelas e colunas devem criar entradas de changelog. As mesmas regras valem: o modo schedule depende de triggers e cron, e o método execute do seu indexer recebe os IDs alterados em lotes. O guia de indexer customizado mostra um exemplo completo.

Importações e o modo schedule

Importações grandes são onde a escolha do modo mais aparece. No modo schedule, a importação grava as linhas e os triggers adicionam entradas de changelog. A importação em si continua rápida, e o cron de índice processa as mudanças em lotes. Com Update on Save, cada linha importada dispara trabalho de índice na hora. Se uma importação ainda demora demais no modo schedule, olhe o código da importação em si, como descrito nas boas práticas de importação de produtos.

FAQ

Os indexers do Magento 2 devem ficar em Update on Save ou Update by Schedule?

Use Update by Schedule em lojas de produção, deixando o customer_grid em Update on Save. Update on Save serve para desenvolvimento local e lojas muito pequenas.

Por que as mudanças nos produtos não aparecem no storefront?

Com os indexers em modo schedule, as mudanças aparecem depois que o cron de índice roda. Se nunca aparecem, provavelmente o cron não está rodando o grupo index.

Por que o indexer:set-mode schedule falha com erro de privilégio?

O modo schedule cria triggers no MySQL. Com binary logging ativo, isso exige SUPER ou log_bin_trust_function_creators igual a 1.

Por que as tabelas _cl do meu banco estão tão grandes?

As entradas de changelog não estão sendo processadas ou limpas, em geral porque o cron não está rodando ou o grupo index está travado.

Atendo como freelancer em Magento e Adobe Commerce, incluindo problemas de indexação e cron. Se você precisa de ajuda com isso, fale comigo.

Artigos relacionados