Estou tentando rastrear uma exclusão de linha que está acontecendo em algum lugar de um aplicativo enorme e extenso. Eu sei que algo excluiu uma linha em uma tabela de banco de dados importante e reduzi quando a exclusão aconteceu em uma janela de tempo de 78 segundos. O aplicativo está distribuído em cerca de 150 servidores, mas um simples grep para "excluir" nos logs desses servidores para essa janela de tempo e alguns minutos de cada lado não está encontrando nada útil, então acho que a exclusão deve ter sido um efeito colateral de outra coisa ou aconteceram dentro do mapeador relacional de objeto que o aplicativo usa.
De qualquer forma, decidi adotar uma abordagem diferente e examinar os logs do postgres em busca da exclusão ofensiva. Ele já deve estar configurado para registrar tudo log_statement = 'all'
, mas isso não está funcionando como esperado. Se eu seguir os logs, esperaria um volume muito maior de mensagens de log passando do que realmente vejo, e se eu usar a interface da Web para visualizar o status atual do aplicativo (gerando consultas ao banco de dados), não Não vejo nenhuma consulta passar. Vejo algumas consultas, mas não muitas, e todas parecem ser de um endereço IP.
O que eu configurei errado? Como faço para que o posgres registre tudo?
Aqui está o conteúdo da seção de log em /var/lib/pgsql/11/data/postgresql.conf
#------------------------------------------------------------------------------
# REPORTING AND LOGGING
#------------------------------------------------------------------------------
# - Where to Log -
log_destination = 'stderr' # Valid values are combinations of
# stderr, csvlog, syslog, and eventlog,
# depending on platform. csvlog
# requires logging_collector to be on.
# This is used when logging to stderr:
logging_collector = on # Enable capturing of stderr and csvlog
# into log files. Required to be on for
# csvlogs.
# (change requires restart)
# These are only used if logging_collector is on:
log_directory = 'log' # directory where log files are written,
# can be absolute or relative to PGDATA
log_filename = 'postgresql-%Y-%m-%d.log' # log file name pattern,
# can include strftime() escapes
#log_file_mode = 0600 # creation mode for log files,
# begin with 0 to use octal notation
log_truncate_on_rotation = on # If on, an existing log file with the
# same name as the new log file will be
# truncated rather than appended to.
# But such truncation only occurs on
# time-driven rotation, not on restarts
# or size-driven rotation. Default is
# off, meaning append to existing files
# in all cases.
log_rotation_age = 1d # Automatic rotation of logfiles will
# happen after that time. 0 disables.
log_rotation_size = 0 # Automatic rotation of logfiles will
# happen after that much log output.
# 0 disables.
# These are relevant when logging to syslog:
#syslog_facility = 'LOCAL0'
#syslog_ident = 'postgres'
#syslog_sequence_numbers = on
#syslog_split_messages = on
# This is only relevant when logging to eventlog (win32):
# (change requires restart)
#event_source = 'PostgreSQL'
# - When to Log -
#log_min_messages = warning # values in order of decreasing detail:
# debug5
# debug4
# debug3
# debug2
# debug1
# info
# notice
# warning
# error
# log
# fatal
# panic
#log_min_error_statement = error # values in order of decreasing detail:
# debug5
# debug4
# debug3
# debug2
# debug1
# info
# notice
# warning
# error
# log
# fatal
# panic (effectively off)
#log_min_duration_statement = -1 # -1 is disabled, 0 logs all statements
# and their durations, > 0 logs only
# statements running at least this number
# of milliseconds
# - What to Log -
#debug_print_parse = off
#debug_print_rewritten = off
#debug_print_plan = off
#debug_pretty_print = on
#log_checkpoints = off
#log_connections = off
#log_disconnections = off
#log_duration = off
#log_error_verbosity = default # terse, default, or verbose messages
#log_hostname = off
log_line_prefix = '%m %h [%p] ' # special values:
# %a = application name
# %u = user name
# %d = database name
# %r = remote host and port
# %h = remote host
# %p = process ID
# %t = timestamp without milliseconds
# %m = timestamp with milliseconds
# %n = timestamp with milliseconds (as a Unix epoch)
# %i = command tag
# %e = SQL state
# %c = session ID
# %l = session line number
# %s = session start timestamp
# %v = virtual transaction ID
# %x = transaction ID (0 if none)
# %q = stop here in non-session
# processes
# %% = '%'
# e.g. '<%u%%%d> '
#log_lock_waits = off # log lock waits >= deadlock_timeout
log_statement = 'all' # none, ddl, mod, all
#log_replication_commands = off
#log_temp_files = -1 # log temporary files equal or larger
# than the specified size in kilobytes;
# -1 disables, 0 logs all temp files
log_timezone = 'UCT'
É possível revogar a configuração log_statement=all. Um superusuário pode apenas executar
SET log_statement=none
em sua sessão (embora a própria instrução SET seja registrada antes que o novo comportamento entre em vigor, deixando evidências). Também pode ser revogado "permanentemente" porALTER user someone set log_statement=none
, ou o análogo deALTER database
. Isso deixaria evidências para trás quando a instrução ALTER fosse executada, mas não quando o usuário individual estabelecesse cada nova conexão. Também poderia ser anulado dentro do próprio arquivo de configuração, bastando ter uma nova configuração mais abaixo no arquivo, ou no arquivo postgresql.auto.conf.Existem outras possibilidades. Se a exclusão for executada de dentro de uma função definida pelo usuário, a chamada da função será registrada, mas a exclusão aninhada não. Se for executado como parte de uma exclusão em cascata de uma chave estrangeira, isso também evitará o registro.
Não vejo como isso evitaria o registro, a menos que também se enquadrasse em uma das possibilidades que já levantei.