Files
2025-11-28 00:29:42 -03:00

780 lines
27 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Roteiro de Ativação do Slony
### LEIA - IMPORTANTE
Caso queira ativar o Slony pela primeira vez utilize o manual seguindo os passos abaixo.
Porém caso queira apenas adicionar um novo Node em uma estrutura do Slony já configurada (Exemplo Fiscal S1), siga o passo a passo do roteiro a seguir:
[`Ativação Slony Fiscal - Adicionando Novo Node`](./ativacao_slony_node.md)
## Destino - Banco Atende.Net
Realize a instalação do Slony no banco:
```
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
```
Realize a liberação do IP do Fiscal ou Vigilância no pg_hba do SGBD:
```
vim /var/lib/pgsql/11/data/pg_hba.conf
Ex.: host all all 172.16.1.18/32 trust
systemctl reload postgresql-11.service
```
Execute o SQL para criação da estrutura (schema replicacao) no SGBD de destino:
```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;
```
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';
```
## Origem - Configurando Node
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 => '172.24.1.24',
dbname => '08573_sc',
port => 65432,
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 (88, 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
# Altere
cod_fiscal="8165" -- Código do schema (Fiscal)
IP_Destino="172.16.1.90" -- IP do Atende.Net - Servidor SLAVE (Destino)
Porta_Destino="65432" - Porta de acesso ao banco Atende.Net - Servidor SLAVE (Destino)
BD_Destino="01611_pinhais" - Nome do banco de dados do Atende.Net - Servidor SLAVE (Destino)
# 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 8561*.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 8561*.log | grep "creating SCHEMA 8561" | uniq -u (Substituir pelo Código do Schema)
```
## Validações
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')
)
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$;
```
## Script de teste
```ruby
# Master (Origem)
create table replicacao.tbteste2(col1 integer primary key, col2 text);
insert into replicacao.tbteste2 values(1,'1');
select * from replicacao.tbteste2;
# Slave (destino)
create table replicacao.tbteste2(col1 integer primary key, col2 text);
# Master (origem)
select replicacao.fn_prepara_contexto('Teste Inicial 2', string_to_array('replicacao.tbteste2',','));
--executar os dois acima juntos
select replicacao.fn_inicia_replicacao_contexto('Teste Inicial 2', 512); --Segundo parametro é o código do cliente (CÓDIGO DO SISTEMA NO GDT)
# Slave (destino)
select * from replicacao.tbteste2; --Já deve ter 1 registro
# Master (origem)
insert into replicacao.tbteste2 values(2,'2');
# Slave (destino)
select * from replicacao.tbteste2; --Deve ter 2 registro
--Tudo deve estar funcionando. Pode apagar a tabela de teste
# Master (origem)
select replicacao.fn_interrompe_replicacao('Teste Inicial 2');
drop table replicacao.tbteste2;
# Slave (destino)
drop table replicacao.tbteste2;
```
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();
```