1187 lines
42 KiB
Markdown
1187 lines
42 KiB
Markdown
# Roteiro Replicação Slony - Fiscal S1
|
||
|
||
> Documentação do roteiro de replicação do sistema Fiscal S1 para o Atende.Net já considerando a versão 16 do PostgreSQL em produção nos clientes.
|
||
>
|
||
> Esse documento é referente a configuração Inicial do Slony. Caso deseje apenas adicionar uma nova replicação ou remover uma já existente, siga a documentação listada abaixo nos processos adicionais!
|
||
>
|
||
> Caso deseje ativar a replicação entre o Master 11.5 e Slave 16, deve-se utilizar esta documentação: [`Replicação Nativa - Fiscal S-1`](../docs/replicacao_nativa_fiscal_s1.md)
|
||
|
||
## Processos Adicionais
|
||
> Os links abaixos são referentes a adição ou remoção de um node.
|
||
|
||
[`1 - Adicionando Node`](../docs/replicacao_slonyfiscal_s1_adicionar_node.md)
|
||
[`2 - Remover Node`](../docs/replicacao_slonyfiscal_s1_remover_node.md)
|
||
[`3 - Remover Estrutura Slony`](../docs/replicacao_slonyfiscal_s1_remover_estrutura_node.md)
|
||
|
||
### Abaixo a representação do funcionamento da estrutura:
|
||
|
||

|
||
|
||
## Destino - Banco Fiscal Slony (00002_www.nfs-e.net_SGDB_1150_SLONY - 192.168.23.11)
|
||
|
||
Checar se o Slony esta instalado e executando:
|
||
|
||
```
|
||
rpm -qi slony1_11
|
||
```
|
||
Caso receba o retorno que a aplicação <b> não está instalada </b>, execute a instalação conforme os passos abaixo:
|
||
|
||
```
|
||
cd /root/
|
||
wget https://datacenter.atende.net/updates/slony1_11.zip
|
||
unzip slony1_11.zip
|
||
cd slony
|
||
rpm -Uvh slony1_11-2.2.10-1.rhel8.x86_64.rpm perl-Switch-2.17-10.el8.noarch.rpm perl-DBD-Pg-3.7.4-4.module_el8.3.0+426+0b4e9c0a.x86_64.rpm perl-Text-Balanced-2.03-395.el8.noarch.rpm perl-Filter-1.58-2.el8.x86_64.rpm perl-SelfLoader-1.23-416.el8.noarch.rpm
|
||
```
|
||
Verificar se o IP do banco Master do Fiscal S1 esta liberado no pg_hba.conf
|
||
```
|
||
vim /var/lib/pgsql/11/data/pg_hba.conf
|
||
Ex.: host all all 192.168.23.10/32 trust (Libera Fiscal S1)
|
||
Ex: host all all 172.16.XXX.XXX/32 trust (IP INT_RT do Cliente)
|
||
|
||
systemctl reload postgresql-11.service
|
||
```
|
||
Conferir as configurações do postgresql.conf (/var/lib/pgsql/11/data/postgresql.conf)
|
||
|
||
```
|
||
wal_level = logical
|
||
max_wal_senders = 3
|
||
max_replication_slots = 3
|
||
max_sync_workers_per_subscription = 2
|
||
```
|
||
Conferir se o usuário replicação existe no Banco de Dados (via pgAdmin):
|
||
|
||
```
|
||
login roles > replicacao
|
||
|
||
Caso não existe, crie o mesmo:
|
||
|
||
CREATE ROLE replicacao WITH LOGIN
|
||
SUPERUSER
|
||
INHERIT
|
||
REPLICATION
|
||
CONNECTION LIMIT -1
|
||
PASSWORD '123456';
|
||
```
|
||
Efetue a criação do database conforme o cliente que você esta ativando a replicação via Slony
|
||
|
||
```
|
||
Exemplo: 00000_cliente
|
||
|
||
CREATE DATABASE "00000_cliente"
|
||
WITH OWNER = dbaipm
|
||
ENCODING = 'LATIN1'
|
||
TABLESPACE = pg_default
|
||
LC_COLLATE = 'pt_BR'
|
||
LC_CTYPE = 'pt_BR'
|
||
CONNECTION LIMIT = -1;
|
||
```
|
||
|
||
Setar os defaults privilégios para o Data Base (substituir o nome 00000_cliente pelo código e nome do cliente):
|
||
|
||
```
|
||
|
||
GRANT ALL ON DATABASE "00000_cliente" TO dbaipm;
|
||
GRANT ALL ON DATABASE "00000_cliente" TO administradores;
|
||
GRANT CONNECT ON DATABASE "00000_cliente" TO consultas;
|
||
GRANT ALL ON DATABASE "00000_cliente" TO migradores;
|
||
GRANT ALL ON DATABASE "00000_cliente" TO sistema;
|
||
REVOKE ALL ON DATABASE "00000_cliente" FROM public;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON TABLES
|
||
TO administradores WITH GRANT OPTION;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT SELECT ON TABLES
|
||
TO consultas WITH GRANT OPTION;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON TABLES
|
||
TO migradores WITH GRANT OPTION;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON TABLES
|
||
TO sistema WITH GRANT OPTION;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON TABLES
|
||
TO atualizacao;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT SELECT, UPDATE, USAGE ON SEQUENCES
|
||
TO administradores WITH GRANT OPTION;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT USAGE ON SEQUENCES
|
||
TO consultas WITH GRANT OPTION;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT SELECT, UPDATE, USAGE ON SEQUENCES
|
||
TO migradores WITH GRANT OPTION;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT SELECT, UPDATE, USAGE ON SEQUENCES
|
||
TO sistema WITH GRANT OPTION;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT SELECT, UPDATE, USAGE ON SEQUENCES
|
||
TO atendenetweb;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT EXECUTE ON FUNCTIONS
|
||
TO public;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT EXECUTE ON FUNCTIONS
|
||
TO administradores WITH GRANT OPTION;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT EXECUTE ON FUNCTIONS
|
||
TO consultas WITH GRANT OPTION;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT EXECUTE ON FUNCTIONS
|
||
TO migradores WITH GRANT OPTION;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT EXECUTE ON FUNCTIONS
|
||
TO sistema WITH GRANT OPTION;
|
||
|
||
ALTER DEFAULT PRIVILEGES
|
||
GRANT EXECUTE ON FUNCTIONS
|
||
TO dbaipm;
|
||
```
|
||
|
||
Criar as extensões
|
||
```
|
||
CREATE EXTENSION pg_buffercache;
|
||
CREATE EXTENSION pg_freespacemap;
|
||
CREATE EXTENSION pg_stat_statements;
|
||
CREATE EXTENSION btree_gist;
|
||
CREATE EXTENSION postgis;
|
||
CREATE EXTENSION postgis_sfcgal;
|
||
```
|
||
|
||
Execute o SQL para criação da estrutura (schema replicacao) no SGBD de destino na database criada no passo anterior:
|
||
|
||
```ruby
|
||
--drop SCHEMA replicacao cascade;
|
||
CREATE SCHEMA replicacao;
|
||
|
||
CREATE SEQUENCE replicacao.sqttblog
|
||
INCREMENT 1
|
||
START 1
|
||
MINVALUE 0
|
||
MAXVALUE 9223372036854775807
|
||
CACHE 1;
|
||
CREATE TABLE replicacao.tblog
|
||
(
|
||
logcodigo bigint NOT NULL DEFAULT nextval('replicacao.sqttblog'::regclass),
|
||
logdatahora timestamp not null default now(),
|
||
logip varchar(30) not null default inet_client_addr(),
|
||
logpid bigint not null default pg_backend_pid(),
|
||
logacao text not null,
|
||
logquery text not null default current_query()
|
||
);
|
||
COMMENT ON COLUMN replicacao.tblog.logcodigo IS 'Código do log';
|
||
COMMENT ON COLUMN replicacao.tblog.logdatahora IS 'Datahora da ocorrencia';
|
||
COMMENT ON COLUMN replicacao.tblog.logip IS 'Ip do client';
|
||
COMMENT ON COLUMN replicacao.tblog.logpid IS 'Pid da conexao';
|
||
COMMENT ON COLUMN replicacao.tblog.logacao IS 'Acao sendo executada';
|
||
COMMENT ON COLUMN replicacao.tblog.logquery IS 'Query';
|
||
|
||
ALTER TABLE replicacao.tblog
|
||
ADD CONSTRAINT pk_tblog PRIMARY KEY(logcodigo);
|
||
|
||
|
||
CREATE SEQUENCE replicacao.sqttbddl
|
||
INCREMENT 1
|
||
START 1
|
||
MINVALUE 0
|
||
MAXVALUE 9223372036854775807
|
||
CACHE 1;
|
||
|
||
CREATE TABLE replicacao.tbddl
|
||
(
|
||
ddlcodigo bigint NOT NULL DEFAULT nextval('replicacao.sqttbddl'::regclass),
|
||
ddlcomando text COLLATE pg_catalog."default" NOT NULL,
|
||
ddldatahora timestamp default now(),
|
||
CONSTRAINT pk_tbddl PRIMARY KEY (ddlcodigo)
|
||
);
|
||
|
||
|
||
--Altera o tablespace das tabelas do IPM Fiscal
|
||
create or replace function replicacao.fn_altera_tablespace()
|
||
returns boolean as
|
||
$body$
|
||
declare
|
||
r_objeto record;
|
||
begin
|
||
--Tabelas
|
||
for r_objeto in (select 'alter table "'||nspname||'"."'||pg_class.relname||'" set tablespace replicacao;' as cmd,
|
||
'"'||nspname||'"."'||pg_class.relname||'"' as nome
|
||
from pg_namespace
|
||
left join pg_class
|
||
on pg_class.relnamespace = pg_namespace.oid
|
||
where translate(pg_namespace.nspname, '1234567890', '') in ('dcarq', '_fiarq', '_gtarq', '_isarq', '_nfarq', '_spunico', '_wgt', '_wnp', '_wsn', 'saudeweb', 'saudewebglo', 'spunico')
|
||
and pg_class.relkind = 'r'
|
||
and pg_class.reltablespace <> (select oid from pg_tablespace where spcname = 'replicacao')
|
||
order by pg_namespace.nspname,
|
||
pg_class.relname)
|
||
loop
|
||
insert into replicacao.tblog (logacao, logquery) values ('Alterando tablespace da tabela '||r_objeto.nome, r_objeto.cmd);
|
||
raise notice 'Alterando tablespace da tabela %.', r_objeto.nome;
|
||
execute r_objeto.cmd;
|
||
end loop;
|
||
|
||
--Índices
|
||
for r_objeto in (select 'alter index "'||nspname||'"."'||pg_class.relname||'" set tablespace replicacao;' as cmd,
|
||
'"'||nspname||'"."'||pg_class.relname||'"' as nome
|
||
from pg_namespace
|
||
left join pg_class
|
||
on pg_class.relnamespace = pg_namespace.oid
|
||
where translate(pg_namespace.nspname, '1234567890', '') in ('dcarq', '_fiarq', '_gtarq', '_isarq', '_nfarq', '_spunico', '_wgt', '_wnp', '_wsn', 'saudeweb', 'saudewebglo', 'spunico')
|
||
and pg_class.relkind = 'i'
|
||
and pg_class.reltablespace <> (select oid from pg_tablespace where spcname = 'replicacao')
|
||
order by pg_namespace.nspname,
|
||
pg_class.relname)
|
||
loop
|
||
insert into replicacao.tblog (logacao, logquery) values ('Alterando tablespace da tabela '||r_objeto.nome, r_objeto.cmd);
|
||
raise notice 'Alterando tablespace do índice %.', r_objeto.nome;
|
||
execute r_objeto.cmd;
|
||
end loop;
|
||
|
||
return true;
|
||
end;
|
||
$body$
|
||
LANGUAGE plpgsql VOLATILE;
|
||
|
||
create or replace function replicacao.fn_remove_relacao_atendenet()
|
||
returns boolean as
|
||
$body$
|
||
declare
|
||
r_fk record;
|
||
begin
|
||
for r_fk in (select *,
|
||
'alter table "'||schema_filha||'"."'||tabela_filha||'" drop constraint "'||conname||'";' as cmd
|
||
from (SELECT pg_constraint.conname,
|
||
schema_pai.nspname as schema_pai,
|
||
tabela_pai.relname as tabela_pai,
|
||
schema_filha.nspname as schema_filha,
|
||
tabela_filha.relname as tabela_filha
|
||
FROM pg_constraint
|
||
INNER JOIN pg_class tabela_filha
|
||
ON tabela_filha.oid = pg_constraint.conrelid
|
||
INNER JOIN pg_namespace schema_filha
|
||
ON schema_filha.oid = tabela_filha.relnamespace
|
||
INNER JOIN pg_class tabela_pai
|
||
ON tabela_pai.oid = pg_constraint.confrelid
|
||
INNER JOIN pg_namespace schema_pai
|
||
ON schema_pai.oid = tabela_pai.relnamespace
|
||
where pg_constraint.contype = 'f'
|
||
and (translate(substr(schema_pai.nspname,1,1),'1234567890','') = '' or
|
||
translate(substr(schema_filha.nspname,1,1),'1234567890','') = '' or
|
||
schema_pai.nspname in ('saudeweb', 'saudewebglo', 'spunico') or
|
||
schema_filha.nspname in ('saudeweb', 'saudewebglo', 'spunico'))
|
||
and pg_constraint.confupdtype <> 'c') orig
|
||
where translate(schema_pai, '1234567890', '') not in ('dcarq', '_fiarq', '_gtarq', '_isarq', '_nfarq', '_spunico', '_wgt', '_wnp', '_wsn', 'saudeweb', 'saudewebglo', 'spunico')
|
||
or translate(schema_filha, '1234567890', '') not in ('dcarq', '_fiarq', '_gtarq', '_isarq', '_nfarq', '_spunico', '_wgt', '_wnp', '_wsn', 'saudeweb', 'saudewebglo', 'spunico'))
|
||
loop
|
||
insert into replicacao.tblog (logacao, logquery) values ('Apagando a FK "'||r_fk.conname||'" da tabela "'||r_fk.schema_filha||'"."'||r_fk.tabela_filha||'".', r_fk.cmd);
|
||
raise notice 'Apagando a FK "%" da tabela "%".', r_fk.conname, r_fk.schema_filha||'"."'||r_fk.tabela_filha;
|
||
execute r_fk.cmd;
|
||
end loop;
|
||
return true;
|
||
end;
|
||
$body$
|
||
LANGUAGE plpgsql VOLATILE;
|
||
```
|
||
|
||
Verificar se o disco de 1,2 TB esta adicionado no Destino:
|
||
|
||
```
|
||
Disco: /var/lib/pgsql/11/tablespaces/replicacao
|
||
|
||
[root@00002-NFSE_SGDB_1150_SLONY ~]# df -h
|
||
Sist. Arq. Tam. Usado Disp. Uso% Montado em
|
||
devtmpfs 8,8G 0 8,8G 0% /dev
|
||
tmpfs 8,8G 12K 8,8G 1% /dev/shm
|
||
tmpfs 8,8G 8,8M 8,8G 1% /run
|
||
tmpfs 8,8G 0 8,8G 0% /sys/fs/cgroup
|
||
/dev/mapper/cl_00000--clean--centos8-root 15G 4,9G 11G 33% /
|
||
/dev/mapper/cl_00000--clean--centos8-home 2,4G 50M 2,4G 3% /home
|
||
/dev/sda2 976M 179M 731M 20% /boot
|
||
/dev/mapper/sgdb04-dados 119G 921M 119G 1% /var/lib/pgsql/11
|
||
/dev/sda1 599M 6,7M 593M 2% /boot/efi
|
||
/dev/mapper/sgdb01-pg_log 19G 168M 19G 1% /var/lib/pgsql/11/data/log
|
||
/dev/mapper/sgdb03-indices 89G 668M 89G 1% /var/lib/pgsql/11/tablespaces/indice
|
||
/dev/mapper/sgdb02-pg_wal 29G 272M 29G 1% /var/lib/pgsql/11/data/pg_wal
|
||
/dev/mapper/cl_00000--clean--centos8-var_log 15G 347M 15G 3% /var/log
|
||
tmpfs 1,8G 0 1,8G 0% /run/user/0
|
||
/dev/mapper/sgdb10-replicacao 1,3T 8,7G 1,2T 1% /var/lib/pgsql/11/tablespaces/replicacao
|
||
[root@00002-NFSE_SGDB_1150_SLONY ~]#
|
||
|
||
```
|
||
|
||
<b> IMPORTANTE: EXECUTAR O PASSO ABAIXO APENAS SE O DISCO NÃO EXISTIR NO SERVIDOR LINUX E O TABLESPACE REPLICACAO NÃO EXISTA NO BANCO DE DADOS DE DESTINO!</b>
|
||
|
||
Deve-se adicionar um HD temporário ao servidor SLAVE (destino) do banco de dados ao qual receberá o tablespace replicacao.
|
||
Como sugestão, adicionar o HD com tamanho de 1234GB, no formato Thin Provision com a controladora SCSI Controller 1, desta forma o HD crescerá somente o necessário e será fácil de identificá-lo para posterior remoção.
|
||
```
|
||
lsblk
|
||
|
||
fdisk /dev/sde
|
||
|
||
#Dispositivo Inicializar Início Fim Setores Tamanho Id Tipo
|
||
#/dev/sde1 2048 2587885567 2587883520 1,2T 8e Linux LVM
|
||
|
||
vgcreate sgdb10 /dev/sde1
|
||
lvcreate -L +1233G -n replicacao sgdb10
|
||
mkfs.xfs /dev/mapper/sgdb10-replicacao
|
||
vim /etc/fstab
|
||
/dev/mapper/sgdb10-replicacao /var/lib/pgsql/11/tablespaces/replicacao xfs defaults 0 1
|
||
mkdir -p /var/lib/pgsql/11/tablespaces/replicacao
|
||
mount /var/lib/pgsql/11/tablespaces/replicacao
|
||
chown postgres.postgres /var/lib/pgsql/11/tablespaces/replicacao/ -R
|
||
chmod 700 /var/lib/pgsql/11/tablespaces/replicacao/ -R
|
||
```
|
||
Criar tablespace replicacao:
|
||
```ruby
|
||
CREATE TABLESPACE replicacao
|
||
OWNER postgres
|
||
LOCATION '/var/lib/pgsql/11/tablespaces/replicacao';
|
||
```
|
||
|
||
|
||
## Destino - Banco Cliente Versão 16 (00000-clean-bdp-01-1600.atende.net)
|
||
|
||
No banco do cliente (PostgreSQL16), criar um disco para a replicação do Fiscal:
|
||
|
||
>Deve-se adicionar um HD temporário ao servidor SLAVE (destino) do banco de dados ao qual receberá o tablespace replicacao.
|
||
>Como sugestão, adicionar o HD com tamanho de 1234GB, no formato Thin Provision com a controladora SCSI Controller 1, desta forma o HD >crescerá somente o necessário e será fácil de identificá-lo para posterior remoção.
|
||
|
||
```
|
||
su - root
|
||
|
||
Criando pasta:
|
||
|
||
mkdir -p /var/lib/postgresql/16/tablespaces/replicacao
|
||
|
||
Adicionando disco:
|
||
|
||
lsblk
|
||
pvcreate /dev/sde
|
||
vgcreate postgresql-vg10 /dev/sde
|
||
lvcreate -l +100%FREE -n lv-replicacao postgresql-vg10
|
||
mkfs.xfs /dev/mapper/postgresql--vg10-lv--replicacao
|
||
blkid | grep replicacao
|
||
blkid | grep replicacao | grep "0cbfc3a7-07d2-483e-885a-73936788b157"
|
||
ls -l /dev/disk/by-id/ | grep dm-7
|
||
#Retorno: dm-uuid-LVM-My295Ba6z7Vl5TX7eyue3b5bCCOtX1NfqddL0ZoIJLfOjD0N9deI8yySYvvRff3h -> ../../dm-7
|
||
|
||
vim /etc/fstab
|
||
|
||
# disco replicacao slony
|
||
/dev/disk/by-id/dm-uuid-LVM-My295Ba6z7Vl5TX7eyue3b5bCCOtX1NfqddL0ZoIJLfOjD0N9deI8yySYvvRff3h /var/lib/postgresql/16/tablespaces/replicacao xfs defaults,noatime,nodiratime 0 1
|
||
|
||
Aplicando permissão para o diretório:
|
||
|
||
chown postgres.postgres /var/lib/postgresql/16/tablespaces/replicacao
|
||
```
|
||
|
||
Verificar se o IP do banco Master do Fiscal S1 esta liberado no pg_hba.conf
|
||
```
|
||
vim /etc/postgresql/16/main/pg_hba.conf
|
||
Ex.: host all all 172.16.1.18/32 trust (Libera Fiscal S1)
|
||
|
||
systemctl reload postgresql.service
|
||
```
|
||
Conferir configurações no arquivo postgresql.conf:
|
||
```
|
||
cd /etc/postgresql/16/main/
|
||
cp postgresql.conf postgresql.bkp-antesslony
|
||
vim postgresql.conf
|
||
|
||
wal_level = logical
|
||
max_wal_senders = 3
|
||
max_replication_slots = 3
|
||
max_sync_workers_per_subscription = 2
|
||
wal_receiver_status_interval = 60s
|
||
wal_receiver_timeout = 300s
|
||
|
||
OBSERVAÇÃO: Se o parametro estiver max_worker_processes = 3, deverá ser alterado para max_worker_processes = 4
|
||
```
|
||
|
||
<b> ATENÇÃO: O RESTART DO SERVIÇO DE BANCO DE DADOS DEVERÁ SER EXECUTADO APÓS AS 18H!
|
||
(systemctl restart postgresql.service)</b>
|
||
|
||
Criar a tablespace replicacao para recebimento dos dados:
|
||
|
||
```ruby
|
||
CREATE TABLESPACE replicacao
|
||
OWNER postgres
|
||
LOCATION '/var/lib/postgresql/16/tablespaces/replicacao';
|
||
```
|
||
```ruby
|
||
--drop SCHEMA replicacao cascade;
|
||
CREATE SCHEMA replicacao;
|
||
|
||
CREATE SEQUENCE replicacao.sqttblog
|
||
INCREMENT 1
|
||
START 1
|
||
MINVALUE 0
|
||
MAXVALUE 9223372036854775807
|
||
CACHE 1;
|
||
CREATE TABLE replicacao.tblog
|
||
(
|
||
logcodigo bigint NOT NULL DEFAULT nextval('replicacao.sqttblog'::regclass),
|
||
logdatahora timestamp not null default now(),
|
||
logip varchar(30) not null default inet_client_addr(),
|
||
logpid bigint not null default pg_backend_pid(),
|
||
logacao text not null,
|
||
logquery text not null default current_query()
|
||
);
|
||
COMMENT ON COLUMN replicacao.tblog.logcodigo IS 'Código do log';
|
||
COMMENT ON COLUMN replicacao.tblog.logdatahora IS 'Datahora da ocorrencia';
|
||
COMMENT ON COLUMN replicacao.tblog.logip IS 'Ip do client';
|
||
COMMENT ON COLUMN replicacao.tblog.logpid IS 'Pid da conexao';
|
||
COMMENT ON COLUMN replicacao.tblog.logacao IS 'Acao sendo executada';
|
||
COMMENT ON COLUMN replicacao.tblog.logquery IS 'Query';
|
||
|
||
ALTER TABLE replicacao.tblog
|
||
ADD CONSTRAINT pk_tblog PRIMARY KEY(logcodigo);
|
||
|
||
|
||
CREATE SEQUENCE replicacao.sqttbddl
|
||
INCREMENT 1
|
||
START 1
|
||
MINVALUE 0
|
||
MAXVALUE 9223372036854775807
|
||
CACHE 1;
|
||
|
||
CREATE TABLE replicacao.tbddl
|
||
(
|
||
ddlcodigo bigint NOT NULL DEFAULT nextval('replicacao.sqttbddl'::regclass),
|
||
ddlcomando text COLLATE pg_catalog."default" NOT NULL,
|
||
ddldatahora timestamp default now(),
|
||
CONSTRAINT pk_tbddl PRIMARY KEY (ddlcodigo)
|
||
);
|
||
|
||
|
||
--Altera o tablespace das tabelas do IPM Fiscal
|
||
create or replace function replicacao.fn_altera_tablespace()
|
||
returns boolean as
|
||
$body$
|
||
declare
|
||
r_objeto record;
|
||
begin
|
||
--Tabelas
|
||
for r_objeto in (select 'alter table "'||nspname||'"."'||pg_class.relname||'" set tablespace replicacao;' as cmd,
|
||
'"'||nspname||'"."'||pg_class.relname||'"' as nome
|
||
from pg_namespace
|
||
left join pg_class
|
||
on pg_class.relnamespace = pg_namespace.oid
|
||
where translate(pg_namespace.nspname, '1234567890', '') in ('dcarq', '_fiarq', '_gtarq', '_isarq', '_nfarq', '_spunico', '_wgt', '_wnp', '_wsn', 'saudeweb', 'saudewebglo', 'spunico')
|
||
and pg_class.relkind = 'r'
|
||
and pg_class.reltablespace <> (select oid from pg_tablespace where spcname = 'replicacao')
|
||
order by pg_namespace.nspname,
|
||
pg_class.relname)
|
||
loop
|
||
insert into replicacao.tblog (logacao, logquery) values ('Alterando tablespace da tabela '||r_objeto.nome, r_objeto.cmd);
|
||
raise notice 'Alterando tablespace da tabela %.', r_objeto.nome;
|
||
execute r_objeto.cmd;
|
||
end loop;
|
||
|
||
--Índices
|
||
for r_objeto in (select 'alter index "'||nspname||'"."'||pg_class.relname||'" set tablespace replicacao;' as cmd,
|
||
'"'||nspname||'"."'||pg_class.relname||'"' as nome
|
||
from pg_namespace
|
||
left join pg_class
|
||
on pg_class.relnamespace = pg_namespace.oid
|
||
where translate(pg_namespace.nspname, '1234567890', '') in ('dcarq', '_fiarq', '_gtarq', '_isarq', '_nfarq', '_spunico', '_wgt', '_wnp', '_wsn', 'saudeweb', 'saudewebglo', 'spunico')
|
||
and pg_class.relkind = 'i'
|
||
and pg_class.reltablespace <> (select oid from pg_tablespace where spcname = 'replicacao')
|
||
order by pg_namespace.nspname,
|
||
pg_class.relname)
|
||
loop
|
||
insert into replicacao.tblog (logacao, logquery) values ('Alterando tablespace da tabela '||r_objeto.nome, r_objeto.cmd);
|
||
raise notice 'Alterando tablespace do índice %.', r_objeto.nome;
|
||
execute r_objeto.cmd;
|
||
end loop;
|
||
|
||
return true;
|
||
end;
|
||
$body$
|
||
LANGUAGE plpgsql VOLATILE;
|
||
|
||
create or replace function replicacao.fn_remove_relacao_atendenet()
|
||
returns boolean as
|
||
$body$
|
||
declare
|
||
r_fk record;
|
||
begin
|
||
for r_fk in (select *,
|
||
'alter table "'||schema_filha||'"."'||tabela_filha||'" drop constraint "'||conname||'";' as cmd
|
||
from (SELECT pg_constraint.conname,
|
||
schema_pai.nspname as schema_pai,
|
||
tabela_pai.relname as tabela_pai,
|
||
schema_filha.nspname as schema_filha,
|
||
tabela_filha.relname as tabela_filha
|
||
FROM pg_constraint
|
||
INNER JOIN pg_class tabela_filha
|
||
ON tabela_filha.oid = pg_constraint.conrelid
|
||
INNER JOIN pg_namespace schema_filha
|
||
ON schema_filha.oid = tabela_filha.relnamespace
|
||
INNER JOIN pg_class tabela_pai
|
||
ON tabela_pai.oid = pg_constraint.confrelid
|
||
INNER JOIN pg_namespace schema_pai
|
||
ON schema_pai.oid = tabela_pai.relnamespace
|
||
where pg_constraint.contype = 'f'
|
||
and (translate(substr(schema_pai.nspname,1,1),'1234567890','') = '' or
|
||
translate(substr(schema_filha.nspname,1,1),'1234567890','') = '' or
|
||
schema_pai.nspname in ('saudeweb', 'saudewebglo', 'spunico') or
|
||
schema_filha.nspname in ('saudeweb', 'saudewebglo', 'spunico'))
|
||
and pg_constraint.confupdtype <> 'c') orig
|
||
where translate(schema_pai, '1234567890', '') not in ('dcarq', '_fiarq', '_gtarq', '_isarq', '_nfarq', '_spunico', '_wgt', '_wnp', '_wsn', 'saudeweb', 'saudewebglo', 'spunico')
|
||
or translate(schema_filha, '1234567890', '') not in ('dcarq', '_fiarq', '_gtarq', '_isarq', '_nfarq', '_spunico', '_wgt', '_wnp', '_wsn', 'saudeweb', 'saudewebglo', 'spunico'))
|
||
loop
|
||
insert into replicacao.tblog (logacao, logquery) values ('Apagando a FK "'||r_fk.conname||'" da tabela "'||r_fk.schema_filha||'"."'||r_fk.tabela_filha||'".', r_fk.cmd);
|
||
raise notice 'Apagando a FK "%" da tabela "%".', r_fk.conname, r_fk.schema_filha||'"."'||r_fk.tabela_filha;
|
||
execute r_fk.cmd;
|
||
end loop;
|
||
return true;
|
||
end;
|
||
$body$
|
||
LANGUAGE plpgsql VOLATILE;
|
||
```
|
||
## Origem - Banco Fiscal (00002_www.nfs-e.net_SGDB - 192.168.23.10)
|
||
|
||
Altere os dados conforme os do cliente que irá fazer a replicação:
|
||
```
|
||
vim /usr/local/slony1/etc/slon_tools.conf
|
||
|
||
$CLUSTER_NAME = 'replication_ipmfiscal';
|
||
add_node(
|
||
node => 1,
|
||
host => '192.168.23.10',
|
||
dbname => '00002_ipmfiscal',
|
||
port => 5432,
|
||
user => 'postgres',
|
||
password => ''
|
||
);
|
||
|
||
add_node(
|
||
node => 2,
|
||
host => '192.168.23.11',
|
||
dbname => '00000_teste',
|
||
port => 5432,
|
||
user => 'postgres',
|
||
password => ''
|
||
|
||
);
|
||
```
|
||
Quando finalizada a configuração do Slave, deve-se prosseguir com o próximo passo:
|
||
```
|
||
/usr/local/slony1/bin/slonik_init_cluster | /usr/local/slony1/bin/slonik
|
||
```
|
||
Após, inicie o cluster:
|
||
```
|
||
/usr/local/slony1/bin/slon_start 1
|
||
/usr/local/slony1/bin/slon_start 2
|
||
```
|
||
|
||
Atualize as funções no master:
|
||
|
||
```ruby
|
||
CREATE SCHEMA replicacao;
|
||
|
||
CREATE TABLE replicacao.tbclientenode
|
||
(
|
||
clicodigo integer not null,
|
||
nodcodigo integer not null
|
||
);
|
||
ALTER TABLE replicacao.tbclientenode
|
||
ADD CONSTRAINT pk_tbclientenode PRIMARY KEY(nodcodigo);
|
||
CREATE UNIQUE INDEX idx_unique_tbclientenode_cliente
|
||
ON replicacao.tbclientenode (clicodigo);
|
||
|
||
CREATE SEQUENCE replicacao.sqttblog
|
||
INCREMENT 1
|
||
START 1
|
||
MINVALUE 0
|
||
MAXVALUE 9223372036854775807
|
||
CACHE 1;
|
||
CREATE TABLE replicacao.tblog
|
||
(
|
||
logcodigo bigint NOT NULL DEFAULT nextval('replicacao.sqttblog'::regclass),
|
||
logdatahora timestamp not null default now(),
|
||
logip varchar(30) not null default inet_client_addr(),
|
||
logpid bigint not null default pg_backend_pid(),
|
||
logacao text not null,
|
||
logquery text not null default current_query()
|
||
);
|
||
COMMENT ON COLUMN replicacao.tblog.logcodigo IS 'Código do log';
|
||
COMMENT ON COLUMN replicacao.tblog.logdatahora IS 'Datahora da ocorrencia';
|
||
COMMENT ON COLUMN replicacao.tblog.logip IS 'Ip do client';
|
||
COMMENT ON COLUMN replicacao.tblog.logpid IS 'Pid da conexao';
|
||
COMMENT ON COLUMN replicacao.tblog.logacao IS 'Acao sendo executada';
|
||
COMMENT ON COLUMN replicacao.tblog.logquery IS 'Query';
|
||
|
||
ALTER TABLE replicacao.tblog
|
||
ADD CONSTRAINT pk_tblog PRIMARY KEY(logcodigo);
|
||
|
||
|
||
drop function if exists replicacao.fn_inicia_replicacao(s_contexto text, a_tabelas text[], i_clicodigo integer);
|
||
|
||
create or replace function replicacao.fn_get_schema_slony()
|
||
returns text as
|
||
$body$
|
||
begin
|
||
return (select schemaname
|
||
from pg_tables
|
||
where tablename = 'sl_node');
|
||
end;
|
||
$body$
|
||
LANGUAGE plpgsql VOLATILE;
|
||
|
||
create or replace function replicacao.fn_adiciona_schema_slony_search_path()
|
||
returns boolean as
|
||
$body$
|
||
declare
|
||
s_search_path text;
|
||
s_schema_name text;
|
||
begin
|
||
s_schema_name := (select replicacao.fn_get_schema_slony());
|
||
|
||
s_search_path := pg_catalog.current_setting('search_path');
|
||
s_search_path := s_search_path||', '||s_schema_name;
|
||
|
||
PERFORM pg_catalog.set_config('search_path', s_search_path, true);
|
||
return true;
|
||
end;
|
||
$body$
|
||
LANGUAGE plpgsql VOLATILE;
|
||
|
||
create or replace function replicacao.fn_remove_schema_slony_search_path()
|
||
returns boolean as
|
||
$body$
|
||
declare
|
||
s_search_path text;
|
||
s_schema_name text;
|
||
begin
|
||
s_schema_name := (select replicacao.fn_get_schema_slony());
|
||
|
||
s_search_path := pg_catalog.current_setting('search_path');
|
||
s_search_path := replace(s_search_path, ', '||s_schema_name, '');
|
||
|
||
PERFORM pg_catalog.set_config('search_path', s_search_path, true);
|
||
return true;
|
||
end;
|
||
$body$
|
||
LANGUAGE plpgsql VOLATILE;
|
||
|
||
create or replace function replicacao.status()
|
||
returns table(cliente integer, lagtime interval, lastevent bigint, lastreceived bigint, sincronizado boolean) as
|
||
$body$
|
||
begin
|
||
perform (select replicacao.fn_adiciona_schema_slony_search_path());
|
||
|
||
drop table if exists tbreturn;
|
||
create temp table tbreturn as
|
||
select tbclientenode.clicodigo as cliente,
|
||
sl_status.st_lag_time as lagtime,
|
||
sl_status.st_last_event as lastevent,
|
||
sl_status.st_last_received as lastreceived,
|
||
sl_status.st_last_event = sl_status.st_last_received as sincronizado
|
||
from sl_status
|
||
left join replicacao.tbclientenode
|
||
on tbclientenode.nodcodigo = sl_status.st_received;
|
||
|
||
perform (select replicacao.fn_remove_schema_slony_search_path());
|
||
|
||
return query(select * from tbreturn);
|
||
end;
|
||
$body$
|
||
LANGUAGE plpgsql VOLATILE;
|
||
|
||
|
||
CREATE OR REPLACE FUNCTION replicacao.fn_get_node_by_clicodigo(i_clicodigo integer)
|
||
RETURNS integer AS
|
||
$BODY$
|
||
declare
|
||
i_node integer;
|
||
begin
|
||
select nodcodigo
|
||
into i_node
|
||
from replicacao.tbclientenode
|
||
where clicodigo = i_clicodigo;
|
||
|
||
if (i_node is null) then
|
||
raise exception 'Não foi possível encontrar um node de replicação para o cliente %.', i_clicodigo;
|
||
end if;
|
||
|
||
return i_node;
|
||
end
|
||
$BODY$
|
||
LANGUAGE plpgsql VOLATILE
|
||
COST 100;
|
||
|
||
CREATE OR REPLACE FUNCTION replicacao.fn_prepara_contexto(
|
||
s_contexto text,
|
||
a_tabelas text[])
|
||
RETURNS boolean AS
|
||
$BODY$
|
||
declare
|
||
i_set integer;
|
||
s_pk text;
|
||
r_tabela record;
|
||
begin
|
||
perform replicacao.fn_adiciona_schema_slony_search_path();
|
||
insert into replicacao.tblog (logacao) values ('fn_prepara_contexto');
|
||
|
||
lock table sl_event;
|
||
|
||
if exists(select 1 from pg_event_trigger where evtname = 'tg_event_trigger_on_execute_ddl_replicacao_ipm') then
|
||
ALTER EVENT TRIGGER tg_event_trigger_on_execute_ddl_replicacao_ipm DISABLE;
|
||
end if;
|
||
|
||
if exists(select 1 from sl_set where set_comment = s_contexto) then
|
||
raise exception 'O contexto "%", já existe.', s_contexto;
|
||
else
|
||
select coalesce(max(set_id),0)+1 into i_set from sl_set;
|
||
perform storeset(i_set, s_contexto);
|
||
end if;
|
||
|
||
for r_tabela in select unnest(a_tabelas) as nometabela
|
||
loop
|
||
if (position('webbased.' in lower(r_tabela.nometabela)) > 0) then
|
||
raise exception 'A tabela "%", está relacionada ao schema webbased, o qual não deve ser replicado.', r_tabela.nometabela;
|
||
end if;
|
||
|
||
if (exists(select 1
|
||
from sl_table
|
||
where tab_nspname||'.'||tab_relname = r_tabela.nometabela)) then
|
||
raise exception 'A tabela "%", já está sendo replicada.', r_tabela.nometabela;
|
||
end if;
|
||
|
||
select indice.relname
|
||
into s_pk
|
||
from pg_class tabela
|
||
left join pg_namespace
|
||
on pg_namespace.oid = tabela.relnamespace
|
||
left join pg_index
|
||
on pg_index.indrelid = tabela.oid
|
||
left join pg_class indice
|
||
on indice.oid = pg_index.indexrelid
|
||
where pg_namespace.nspname||'.'||tabela.relname = r_tabela.nometabela
|
||
and pg_index.indisprimary;
|
||
|
||
if coalesce(s_pk,'') = '' then
|
||
raise exception 'A tabela "%", não possui chave primária.', r_tabela.nometabela;
|
||
end if;
|
||
|
||
perform setaddtable(i_set, (select coalesce(max(tab_id),0)+1 from sl_table), r_tabela.nometabela, s_pk, '');
|
||
end loop;
|
||
|
||
if exists(select 1 from pg_event_trigger where evtname = 'tg_event_trigger_on_execute_ddl_replicacao_ipm') then
|
||
ALTER EVENT TRIGGER tg_event_trigger_on_execute_ddl_replicacao_ipm ENABLE;
|
||
end if;
|
||
|
||
perform replicacao.fn_remove_schema_slony_search_path();
|
||
|
||
return true;
|
||
end
|
||
$BODY$
|
||
LANGUAGE plpgsql VOLATILE
|
||
COST 100;
|
||
|
||
CREATE OR REPLACE FUNCTION replicacao.fn_inicia_replicacao_contexto(
|
||
s_contexto text,
|
||
i_clicodigo integer)
|
||
RETURNS boolean AS
|
||
$BODY$
|
||
begin
|
||
perform replicacao.fn_adiciona_schema_slony_search_path();
|
||
insert into replicacao.tblog (logacao) values ('fn_inicia_replicacao_contexto');
|
||
|
||
if exists(select 1 from pg_event_trigger where evtname = 'tg_event_trigger_on_execute_ddl_replicacao_ipm') then
|
||
ALTER EVENT TRIGGER tg_event_trigger_on_execute_ddl_replicacao_ipm DISABLE;
|
||
end if;
|
||
|
||
perform replicacao.fn_adiciona_slave_replicacao(s_contexto, i_clicodigo);
|
||
|
||
if exists(select 1 from pg_event_trigger where evtname = 'tg_event_trigger_on_execute_ddl_replicacao_ipm') then
|
||
ALTER EVENT TRIGGER tg_event_trigger_on_execute_ddl_replicacao_ipm ENABLE;
|
||
end if;
|
||
|
||
perform replicacao.fn_remove_schema_slony_search_path();
|
||
|
||
return true;
|
||
end
|
||
$BODY$
|
||
LANGUAGE plpgsql VOLATILE
|
||
COST 100;
|
||
|
||
CREATE OR REPLACE FUNCTION replicacao.fn_interrompe_replicacao(s_contexto text)
|
||
RETURNS boolean AS
|
||
$BODY$
|
||
declare
|
||
i_set integer;
|
||
begin
|
||
perform replicacao.fn_adiciona_schema_slony_search_path();
|
||
insert into replicacao.tblog (logacao) values ('fn_interrompe_replicacao('''||s_contexto||''')');
|
||
|
||
if not exists(select 1 from sl_set where set_comment = s_contexto) then
|
||
raise exception 'O contexto "%", não existe.', s_contexto;
|
||
else
|
||
select set_id into i_set from sl_set where set_comment = s_contexto;
|
||
end if;
|
||
|
||
perform dropset(i_set);
|
||
|
||
perform replicacao.fn_remove_schema_slony_search_path();
|
||
|
||
return true;
|
||
end
|
||
$BODY$
|
||
LANGUAGE plpgsql VOLATILE
|
||
COST 100;
|
||
|
||
CREATE OR REPLACE FUNCTION replicacao.fn_interrompe_replicacao_tabela(s_tabela text)
|
||
RETURNS boolean AS
|
||
$BODY$
|
||
begin
|
||
perform replicacao.fn_adiciona_schema_slony_search_path();
|
||
insert into replicacao.tblog (logacao) values ('fn_interrompe_replicacao_tabela('''||s_tabela||''')');
|
||
|
||
if (not exists(select tab_id
|
||
from sl_table
|
||
where tab_nspname||'.'||tab_relname = s_tabela)) then
|
||
raise exception 'A tabela "%", não está sendo replicada.', s_tabela;
|
||
end if;
|
||
|
||
perform setdroptable((select tab_id
|
||
from sl_table
|
||
where tab_nspname||'.'||tab_relname = s_tabela));
|
||
|
||
perform replicacao.fn_remove_schema_slony_search_path();
|
||
|
||
return true;
|
||
end
|
||
$BODY$
|
||
LANGUAGE plpgsql VOLATILE
|
||
COST 100;
|
||
|
||
CREATE OR REPLACE FUNCTION replicacao.fn_adiciona_slave_replicacao(
|
||
s_contexto text,
|
||
i_clicodigo integer)
|
||
RETURNS boolean AS
|
||
$BODY$
|
||
declare
|
||
i_set integer;
|
||
i_node_master integer;
|
||
i_node_slave integer;
|
||
begin
|
||
perform replicacao.fn_adiciona_schema_slony_search_path();
|
||
i_node_master = 1;
|
||
i_node_slave = replicacao.fn_get_node_by_clicodigo(i_clicodigo);
|
||
|
||
insert into replicacao.tblog (logacao) values ('fn_adiciona_slave_replicacao');
|
||
|
||
if not exists(select 1 from sl_set where set_comment = s_contexto) then
|
||
raise exception 'O contexto "%", não existe.', s_contexto;
|
||
else
|
||
select set_id into i_set from sl_set where set_comment = s_contexto;
|
||
|
||
if exists(select 1 from sl_set where set_comment = s_contexto and age(xmin) = 0) then
|
||
raise exception 'O contexto "%", não deve ser preparado e iniciado na mesma execução.', s_contexto;
|
||
end if;
|
||
end if;
|
||
|
||
if not exists(select 1 from sl_node where no_id = i_node_master) then
|
||
raise exception 'O node de replicação "%", não existe.', i_node_master;
|
||
end if;
|
||
|
||
if not exists(select 1 from sl_node where no_id = i_node_slave) then
|
||
raise exception 'O node de replicação "%", não existe.', i_node_slave;
|
||
end if;
|
||
|
||
perform subscribeset(i_set, i_node_master, i_node_slave, false, false);
|
||
|
||
perform replicacao.fn_remove_schema_slony_search_path();
|
||
|
||
return true;
|
||
end
|
||
$BODY$
|
||
LANGUAGE plpgsql VOLATILE
|
||
COST 100;
|
||
|
||
CREATE OR REPLACE FUNCTION replicacao.fn_interrompe_replicacao_tabelas_sem_slave()
|
||
RETURNS boolean AS
|
||
$BODY$
|
||
declare
|
||
s_objetos text;
|
||
r_record record;
|
||
begin
|
||
perform replicacao.fn_adiciona_schema_slony_search_path();
|
||
insert into replicacao.tblog (logacao) values ('fn_interrompe_replicacao_tabelas_sem_slave');
|
||
|
||
lock table sl_set;
|
||
|
||
for r_record in
|
||
select sl_table.tab_nspname||'.'||sl_table.tab_relname as table
|
||
from sl_table
|
||
left join sl_set
|
||
on sl_set.set_id = sl_table.tab_set
|
||
left join sl_subscribe
|
||
on sl_subscribe.sub_set = sl_set.set_id
|
||
where sl_subscribe.sub_receiver is null
|
||
loop
|
||
perform replicacao.fn_interrompe_replicacao_tabela(r_record.table);
|
||
end loop;
|
||
|
||
perform replicacao.fn_remove_schema_slony_search_path();
|
||
perform replicacao.fn_adiciona_schema_slony_search_path();
|
||
|
||
for r_record in
|
||
select sl_set.set_comment as contexto
|
||
from sl_set
|
||
left join sl_subscribe
|
||
on sl_subscribe.sub_set = sl_set.set_id
|
||
where sl_subscribe.sub_receiver is null
|
||
loop
|
||
perform replicacao.fn_interrompe_replicacao(r_record.contexto);
|
||
end loop;
|
||
|
||
perform replicacao.fn_remove_schema_slony_search_path();
|
||
|
||
return true;
|
||
end
|
||
$BODY$
|
||
LANGUAGE plpgsql VOLATILE
|
||
COST 100;
|
||
|
||
CREATE OR REPLACE FUNCTION replicacao.fn_remove_slave_replicacao(
|
||
s_contexto text,
|
||
i_clicodigo integer)
|
||
RETURNS text AS
|
||
$BODY$
|
||
declare
|
||
i_set integer;
|
||
i_node_master integer;
|
||
i_node_slave integer;
|
||
begin
|
||
perform replicacao.fn_adiciona_schema_slony_search_path();
|
||
i_node_master = 1;
|
||
i_node_slave = replicacao.fn_get_node_by_clicodigo(i_clicodigo);
|
||
|
||
insert into replicacao.tblog (logacao) values ('fn_remove_slave_replicacao');
|
||
|
||
if not exists(select 1 from sl_set where set_comment = s_contexto) then
|
||
raise exception 'O contexto "%", não existe.', s_contexto;
|
||
else
|
||
select set_id into i_set from sl_set where set_comment = s_contexto;
|
||
|
||
if exists(select 1 from sl_set where set_comment = s_contexto and age(xmin) = 0) then
|
||
raise exception 'O contexto "%", não deve ser preparado e iniciado na mesma execução.', s_contexto;
|
||
end if;
|
||
end if;
|
||
|
||
if not exists(select 1 from sl_node where no_id = i_node_master) then
|
||
raise exception 'O node de replicação "%", não existe.', i_node_master;
|
||
end if;
|
||
|
||
if not exists(select 1 from sl_node where no_id = i_node_slave) then
|
||
raise exception 'O node de replicação "%", não existe.', i_node_slave;
|
||
end if;
|
||
|
||
raise notice 'Executar no slave: "select * from _replication_ipmfiscal.unsubscribeset(%, %, false);"', i_set, i_node_slave;
|
||
|
||
/*perform unsubscribeset(i_set, i_node_slave, false);*/
|
||
|
||
perform replicacao.fn_remove_schema_slony_search_path();
|
||
|
||
return format('Executar no slave: "select * from _replication_ipmfiscal.unsubscribeset(%s, %s, false);"', i_set, i_node_slave);
|
||
end
|
||
$BODY$
|
||
LANGUAGE plpgsql VOLATILE
|
||
COST 100;
|
||
|
||
|
||
CREATE SEQUENCE replicacao.sqttbddl
|
||
INCREMENT 1
|
||
START 1
|
||
MINVALUE 0
|
||
MAXVALUE 9223372036854775807
|
||
CACHE 1;
|
||
|
||
CREATE TABLE replicacao.tbddl
|
||
(
|
||
ddlcodigo bigint NOT NULL DEFAULT nextval('replicacao.sqttbddl'::regclass),
|
||
ddlcomando text COLLATE pg_catalog."default" NOT NULL,
|
||
ddldatahora timestamp default now(),
|
||
CONSTRAINT pk_tbddl PRIMARY KEY (ddlcodigo)
|
||
);
|
||
|
||
CREATE OR REPLACE FUNCTION replicacao.fn_event_trigger_on_execute_ddl()
|
||
RETURNS event_trigger
|
||
LANGUAGE 'plpgsql'
|
||
COST 100
|
||
VOLATILE NOT LEAKPROOF
|
||
AS $BODY$
|
||
BEGIN
|
||
if position((select replicacao.fn_get_schema_slony()) in current_query()) = 0 then
|
||
insert into replicacao.tbddl (ddlcomando) values (current_query());
|
||
end if;
|
||
END
|
||
$BODY$;
|
||
```
|
||
|
||
Acessar o banco do fiscal, schema replicação, tabela tbclientenode (alterar o código do cliente) não necessário o SQL abaixo:
|
||
```ruby
|
||
insert into replicacao.tbclientenode (clicodigo, nodcodigo) values (55, 2);
|
||
|
||
clicodigo = (Codigo do sistema) do cliente no Atende.Net
|
||
nodcodigo - Código do node criado no slon_tools.conf ou no arquivo relacionado a sua adição no master.
|
||
|
||
Obs: Para cada node SLAVE (Destino) adicional deve-se executar o procedimento descrito no chamado: 480647, anexo 9 (Migração Fiscal - Criando Nodes)
|
||
```
|
||
Ao final, deve-se executar o script para criar a estrutura no banco slave, para isto edite o script de backup que fica no servidor master(IPMFiscal)
|
||
```ruby
|
||
|
||
su - postgres
|
||
|
||
vim backup_estrutura_slony.sh
|
||
|
||
# Altere
|
||
cod_fiscal="8043" -- Código do schema (Fiscal)
|
||
|
||
# Destino 11 Fiscal Slony
|
||
IP_Destino_11="192.168.23.11" (IP do Banco de Dados do Slony intermediário, não precisa ser alterado)
|
||
Porta_Destino_11="5432" (Portal default sem necessidade de alterar)
|
||
BD_Destino_11="00000_teste" (Informe o database do cliente que irá ativar a replicacao)
|
||
|
||
# Destino Cliente Atende
|
||
IP_Destino_16="172.16.XXX.XXX ou 172.24.XXX.XXX" (Informe a INT_RT do cliente Atende.Net - Banco de Dados PostgreSQL 16)
|
||
Porta_Destino_16="65432" (Porta default)
|
||
BD_Destino_16="00000_teste" (Informe o nome da database do cliente)
|
||
|
||
|
||
# Execute o script - O backup e o log serão criados na storage de backup "X:\STORE\Transferir\00002_ipmfiscal"
|
||
su - postgres
|
||
./backup_estrutura_slony.sh
|
||
|
||
# Ao final, confira os log´s.
|
||
cat 8043*.log | grep ERROR | uniq -u
|
||
|
||
# Conferir se os Schemas foram criados, o comando deve retornar os Schemas restaurados, caso não existe favor verificar
|
||
cat 8043*.log | grep "creating SCHEMA 8043" | uniq -u (Substituir pelo Código do Schema)
|
||
```
|
||
## Validações (00002_www.nfs-e.net_SGDB_1150_SLONY - 192.168.23.11)
|
||
Validar Schema e Authorization no banco destino:
|
||
```ruby
|
||
-- Schema: migracao_fiscal
|
||
-- DROP SCHEMA migracao_fiscal;
|
||
CREATE SCHEMA migracao_fiscal
|
||
AUTHORIZATION dbaipm;
|
||
|
||
GRANT ALL ON SCHEMA migracao_fiscal TO dbaipm;
|
||
GRANT ALL ON SCHEMA migracao_fiscal TO administradores;
|
||
GRANT USAGE ON SCHEMA migracao_fiscal TO consultas;
|
||
GRANT ALL ON SCHEMA migracao_fiscal TO migradores;
|
||
GRANT ALL ON SCHEMA migracao_fiscal TO sistema;
|
||
```
|
||
Setar privilégios schemas fiscal:
|
||
```ruby
|
||
do
|
||
$body$
|
||
declare
|
||
r_objeto record;
|
||
begin
|
||
for r_objeto in (select 'GRANT ALL ON SCHEMA "'||pg_namespace.nspname||'" TO dbaipm;
|
||
GRANT ALL ON SCHEMA "'||pg_namespace.nspname||'" TO administradores;
|
||
GRANT USAGE ON SCHEMA "'||pg_namespace.nspname||'" TO consultas;
|
||
GRANT ALL ON SCHEMA "'||pg_namespace.nspname||'" TO migradores;
|
||
GRANT ALL ON SCHEMA "'||pg_namespace.nspname||'" TO sistema;' as cmd,
|
||
'"'||pg_namespace.nspname||'"' as nome
|
||
from pg_namespace
|
||
where translate(pg_namespace.nspname, '1234567890', '') in ('dcarq', '_fiarq', '_gtarq', '_isarq', '_nfarq', '_spunico', '_wgt', '_wnp', '_wsn', 'saudeweb', 'saudewebglo', 'spunico', 'migracao_fiscal', 'migracao_saude')
|
||
)
|
||
loop
|
||
insert into replicacao.tblog (logacao, logquery) values ('Alterando grants do schema '||r_objeto.nome, r_objeto.cmd);
|
||
raise notice 'Alterando grants do schema %.', r_objeto.nome;
|
||
execute r_objeto.cmd;
|
||
end loop;
|
||
end;
|
||
$body$;
|
||
```
|
||
Liberar porta 65434 no Firewall do cliente, para a conexão entre PG11 x PG16:
|
||
Vá em: Firewall > Rules > LAN
|
||
Destination: 65434
|
||
Description: Bdp-1150-SLONY
|
||
|
||

|
||
|
||
## Script de teste
|
||
```ruby
|
||
# Master (Origem)
|
||
create table replicacao.tbteste4(col1 integer primary key, col2 text);
|
||
insert into replicacao.tbteste4 values(1,'1');
|
||
select * from replicacao.tbteste4;
|
||
|
||
# Slave (11.5)
|
||
create table replicacao.tbteste4(col1 integer primary key, col2 text);
|
||
|
||
# Destino (16)
|
||
create table replicacao.tbteste4(col1 integer primary key, col2 text);
|
||
|
||
# Master (origem)
|
||
select replicacao.fn_prepara_contexto('Teste Inicial 4', string_to_array('replicacao.tbteste4',','));
|
||
|
||
select replicacao.fn_inicia_replicacao_contexto('Teste Inicial 4', 55); --Segundo parametro é o código do cliente (CÓDIGO DO SISTEMA NO GDT)
|
||
|
||
# Slave (11.5)
|
||
select * from replicacao.tbteste4; --Já deve ter 1 registro
|
||
|
||
CREATE PUBLICATION publication_mig_ipm_fiscal_00000_cliente;
|
||
ALTER PUBLICATION publication_mig_ipm_fiscal_00000_cliente ADD table replicacao.tbteste4;
|
||
|
||
# Destino (16)
|
||
CREATE SUBSCRIPTION subscription_mig_ipm_fiscal_00000_cliente CONNECTION 'host=172.16.1.18 port=65434 user=replicacao dbname=00000_cliente' PUBLICATION publication_mig_ipm_fiscal_00000_cliente;
|
||
select * from replicacao.tbteste4;
|
||
|
||
# Master (origem)
|
||
insert into replicacao.tbteste4 values(2,'2');
|
||
|
||
# Slave (11.5)
|
||
select * from replicacao.tbteste4; --Deve ter 2 registro
|
||
--Tudo deve estar funcionando. Pode apagar a tabela de teste
|
||
|
||
# Destino (16)
|
||
select * from replicacao.tbteste4; --Deve ter 2 registro
|
||
--Tudo deve estar funcionando. Pode apagar a tabela de teste
|
||
|
||
# Master (origem)
|
||
select replicacao.fn_interrompe_replicacao('Teste Inicial 4');
|
||
drop table replicacao.tbteste4;
|
||
|
||
# Slave (11.5)
|
||
drop PUBLICATION publication_mig_ipm_fiscal_00000_cliente;
|
||
drop table replicacao.tbteste4;
|
||
|
||
# Destino (16)
|
||
ALTER SUBSCRIPTION subscription_mig_ipm_fiscal_00000_cliente DISABLE;
|
||
DROP SUBSCRIPTION subscription_mig_ipm_fiscal_00000_cliente;
|
||
drop table replicacao.tbteste4;
|
||
```
|
||
Parar o serviço e iniciar novamente, após, verifique o Lag Time:
|
||
```
|
||
/usr/local/slony1/bin/slon_kill
|
||
|
||
/usr/local/slony1/bin/slon_start 1
|
||
/usr/local/slony1/bin/slon_start 2
|
||
```
|
||
```ruby
|
||
select * from replicacao.status();
|
||
``` |