Eu tenho vários aplicativos C# em que preciso garantir que haja apenas uma instância do aplicativo em execução em um determinado esquema.
Estou migrando do Oracle para o PostgreSQL 10.
No Oracle, eu executaria a seguinte consulta:
select sid, username, machine, program, logon_time
from sys.v_$session v
where status not in ('KILLED')
and upper('\' || machine) not like upper('%\' || :MACHINE)
and upper(username) = upper(:USERNAME)
and upper(program) = upper(:PROGRAM)
Eu uso Environment.MachineName em meus aplicativos para obter o valor do parâmetro MACHINE .
Eu reescrevi a consulta para o PostgreSQL da seguinte forma:
select pid, user, client_hostname, application_name, backend_start
from pg_stat_activity
where upper(state) not in ('KILLED')
and upper('\\' || client_hostname) not like upper('%\\' || :MACHINE)
and upper(user) = upper(:USERNAME)
and upper(application_name) = upper(:APPNAME)
Eu adicionei o ApplicationName à minha cadeia de conexão e habilitei a log_hostname
configuração no meu banco de dados para preencher as colunas application_name
e em , respectivamente.client_hostname
pg_stat_activity
O problema que me deparei é que, ao executar a aplicação em uma máquina virtual, a client_address
coluna mostra o endereço IP da máquina física que está hospedando a VM, não o endereço IP da máquina virtual e, portanto, client_hostname
está errado também .
Estou fazendo algo errado? Existe uma maneira de fazer com que meu aplicativo envie as informações corretas para o PostgreSQL ao conectar?
Acredito que o nome da máquina no Oracle seja informado voluntariamente pelo cliente ao servidor, por isso funciona mesmo atrás do NAT.
PostgreSQL tem apenas um campo auto-relatado, então eu acho que o que você terá que fazer é colocar "nome do programa" e "nome da máquina" no campo ApplicationName com algum tipo de delimitador entre eles.
O
client_addr
é realmente o endereço IP na outra extremidade da conexão TCP/IP. Se a VM tiver acesso direto à rede, portanto, seu próprio endereço IP, é isso que o PostgreSQL deve ver.Mas se a VM não tiver acesso direto à rede global e, em vez disso, passar por algum NAT (normalmente no host) ou qualquer gateway de aplicativo, o PostgreSQL só poderá ver, no nível da rede, o endereço IP deste último componente que fica na frente da VM.
Além disso,
client_hostname
é um nome, derivado do endereço IP. As resoluções podem mudar com o tempo, portanto, pode ser preferível registrar em vez (ou além) o arquivoclient_addr
.client_hostname
também é preenchido apenas selog_hostname
estiver ativado no arquivo de configuração.Lembre-se também de que a conexão pode acontecer por IPv6 (talvez não agora, mas no futuro, dependendo da sua configuração e configuração, é claro), portanto, certifique-se de não ter falsas suposições sobre o conteúdo (formato e comprimento) do
client_addr
. Se você precisar armazená-lo em outro lugar, por exemplo, tome cuidado para usar o tipo dedicado do PostgreSQL para isso, ou seja,inet
que será superior aotext
.Nota de passagem neste documento: Recomendações de Logging para Servidores Virados para a Internet que se resume ao fato de que hoje em dia, especificamente para IPv4, devido à escassez deste espaço e como ele é gerenciado em vários lugares, faz sentido registrar não apenas o endereço IP do cliente, mas também o número da porta TCP do cliente.
Isso seria
client_port
no PostgreSQL.