-
Notifications
You must be signed in to change notification settings - Fork 0
fix(db): Fase 6 pós-colapso — idle_*_timeout + log queries lentas #336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
90 changes: 90 additions & 0 deletions
90
supabase/migrations/20260525132458_colapso_fase6_idle_timeouts_e_log_slow_queries.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| -- ============================================================================ | ||
| -- Fase 6 (Follow-up Pós-Colapso 2026-05-24) | ||
| -- ============================================================================ | ||
| -- Fecha 2 dos 3 itens P0/P1 pendentes documentados em: | ||
| -- docs/RELATORIO_COLAPSO_2026-05-24.md | ||
| -- | ||
| -- Achados endereçados: | ||
| -- #3 Conexões PostgREST idle persistem por dias (causa raiz #3 do colapso) | ||
| -- idle_session_timeout = 0 -> 10 min | ||
| -- idle_in_transaction_session_timeout = 0 -> 60 s | ||
| -- | ||
| -- #10 Queries lentas não eram logadas (forense pós-mortem ficava cego) | ||
| -- log_min_duration_statement = -1 -> 2000 ms | ||
| -- | ||
| -- ---------------------------------------------------------------------------- | ||
| -- Contexto da decisão técnica | ||
| -- ---------------------------------------------------------------------------- | ||
| -- Os ALTER DATABASE abaixo passam normalmente para o role da aplicação. | ||
| -- | ||
| -- log_min_duration_statement, porém, tem Context: superuser no Postgres. | ||
| -- ALTER DATABASE postgres SET log_min_duration_statement = '2000' RETORNA | ||
| -- ERROR 42501 (permission denied). A doc oficial do Supabase documenta que | ||
| -- a extensão supautils libera essa modificação APENAS no nível de ROLE: | ||
| -- | ||
| -- https://supabase.com/docs/guides/database/custom-postgres-config | ||
| -- #superuser-settings | ||
| -- | ||
| -- Por isso este parâmetro usa ALTER ROLE em vez de ALTER DATABASE. | ||
| -- | ||
| -- ---------------------------------------------------------------------------- | ||
| -- Aplicado via MCP em 2026-05-25 13:00-13:20 UTC | ||
| -- Executor: Abner Silva (TI Promo Brindes) | ||
| -- Esta migration registra a mudança no histórico do repo. Como os 3 ALTERs | ||
| -- são idempotentes, a reaplicação pelo pipeline é segura. | ||
| -- ============================================================================ | ||
|
|
||
| -- ---------------------------------------------------------------------------- | ||
| -- Achado #3 - Settings de timeout para conexões idle | ||
| -- ---------------------------------------------------------------------------- | ||
| -- Aplica a NOVAS conexões. Sessões já abertas mantêm o valor antigo até serem | ||
| -- recicladas. Validação imediata da aplicação no banco mostrou: | ||
| -- - PID 2376 (PostgREST idle há 10.9 dias) foi eliminado automaticamente | ||
| -- - Conexões idle totais: 8 -> 4 | ||
| -- - Idle > 1 dia: 1 -> 0 | ||
| -- ---------------------------------------------------------------------------- | ||
| ALTER DATABASE postgres SET idle_session_timeout = '600000'; -- 10 min em ms | ||
| ALTER DATABASE postgres SET idle_in_transaction_session_timeout = '60000'; -- 60 s em ms | ||
|
|
||
| -- ---------------------------------------------------------------------------- | ||
| -- Achado #10 - Logar queries com duração > 2 s | ||
| -- ---------------------------------------------------------------------------- | ||
| -- Persistido em pg_roles.rolconfig. Validação imediata: | ||
| -- SELECT rolconfig FROM pg_roles WHERE rolname = 'postgres'; | ||
| -- -- retorna ["search_path=...", "log_min_duration_statement=2000"] | ||
| -- ---------------------------------------------------------------------------- | ||
| ALTER ROLE "postgres" SET "log_min_duration_statement" TO '2000'; -- 2 s em ms | ||
|
|
||
| -- ============================================================================ | ||
| -- Validação esperada pós-deploy (rodar manualmente no SQL Editor) | ||
| -- ============================================================================ | ||
| -- | ||
| -- -- Settings persistidos no level DATABASE: | ||
| -- SELECT split_part(unnest(setconfig), '=', 1) AS setting, | ||
| -- split_part(unnest(setconfig), '=', 2) AS valor | ||
| -- FROM pg_db_role_setting | ||
| -- WHERE setdatabase = (SELECT oid FROM pg_database WHERE datname='postgres'); | ||
| -- -- Esperado: | ||
| -- -- idle_session_timeout = 600000 | ||
| -- -- idle_in_transaction_session_timeout = 60000 | ||
| -- | ||
| -- -- Setting persistido no level ROLE: | ||
| -- SELECT rolname, rolconfig FROM pg_roles WHERE rolname = 'postgres'; | ||
| -- -- rolconfig deve conter "log_min_duration_statement=2000" | ||
| -- | ||
| -- -- Conexões idle de longa duração (deve ser zero ou muito poucas): | ||
| -- SELECT pid, application_name, | ||
| -- round(EXTRACT(EPOCH FROM (now() - state_change)) / 60)::int AS idle_min | ||
| -- FROM pg_stat_activity | ||
| -- WHERE state = 'idle' | ||
| -- AND state_change < now() - interval '1 hour' | ||
| -- AND backend_type = 'client backend' | ||
| -- ORDER BY state_change ASC; | ||
| -- | ||
| -- ============================================================================ | ||
| -- Pendência remanescente do RELATORIO_COLAPSO_2026-05-24 | ||
| -- ============================================================================ | ||
| -- #6 Auth Connection Strategy: Absolute (10) -> Percentage (15%) | ||
| -- Não pode ser feito por SQL. Caminho: Supabase Dashboard -> | ||
| -- Authentication -> Settings -> Database Connection Strategy. | ||
| -- ============================================================================ | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting
log_min_duration_statementonpostgresonly affects sessions that authenticate as that role; PostgreSQL role GUCs are applied at login for that specific role. In Supabase, user traffic through PostgREST typically runs asauthenticator(and switches toanon/authenticated), so this migration can leave the main API query path unlogged and does not fully resolve the slow-query observability gap it targets.Useful? React with 👍 / 👎.