2008-10-23

Черновик. Репликация средствами bucardo. №3

Попытка №2 опять неудачная. Непонятно, почему. Попытка 3.

Итак все тот же SLES10 SP2 и PostgreSQL 8.2.5

Сразу после установки SLES по умолчанию имеем следующий набор модулей:

perl-Bit-Vector-6.4-13.5
perl-Bootloader-0.4.19.12-0.3

perl-Carp-Clan-5.3-13.5
perl-Compress-Zlib-1.35-14.2
perl-Config-Crontab-1.11-12.2
perl-Config-IniFiles-2.39-13.4
perl-Crypt-SmbHash-0.12-13.2
perl-Date-Calc-5.4-14.5
perl-Digest-MD4-1.5-13.2
perl-Digest-SHA1-2.10-15.2
perl-gettext-1.05-13.2
perl-Parse-RecDescent-1.80-259.2
perl-PDA-Pilot-0.11.8-138.2
perl-TermReadKey-2.30-13.2
perl-TimeDate-1.16-136.2
perl-URI-1.35-15.2
perl-X500-DN-0.28-133.2
perl-XML-Parser-2.34-43.2
perl-XML-Writer-0.600-13.2

Возможно в попытке №2 чего-то нехватило, возник конфликт с уже установленым или еще непонятно что. Делаем заново и внимательно. Ставим модули в след последовательности:

Pod-Escapes-1.04
Pod-Simple-2.06
Test-Pod-1.00
Net-Daemon-0.27
PlRPC-0.2020
DBI-1.51
ExtUtils-CBuilder-0.24
ExtUtils::MakeMaker 6.32
IO-1.2301
Storable-2.16
POE-Test-Loops-1.002
Curses-1.13
Event-1.10
Устанавливаем пакет gtk-devel
Gtk-Perl-0.7009 (perl Makefile.PL --without-guessing). Модуль загадочный... Дохрена всего нужно проставить из Gnome. В принципе пакет опциональный, так что с ним не заморачиваемся, ставим с указанной опцией. Но в уме держим, что модуль установили ненастроенный.)
IO-Tty-1.02
Test-Pod-1.14
HTML-Tagset-3.20
HTML-Parser-3.56
libwww-perl-5.800
Socket6-0.15
Tk-804.027 (make test нужно делать в X-ах, я например открыл VNC соединение, и тесты делал в нем, иначе все тесты провалятся)
Devel-Symdump-2.08
Pod-Coverage-0.19
Test-Pod-Coverage-1.06
POE-1.003 (make test нужно делать в X-ах, я например открыл VNC соединение, и тесты делал в нем, иначе все тесты провалятся)
Number-Compare-0.01
Text-Glob-0.08
File-Find-Rule-0.30
PathTools-3.2701
Test-Pod-Coverage-1.08
Test-Simple-0.80
Module-CoreList-2.15
Digest-SHA-5.47
Module-Signature-0.55
ExtUtils-ParseXS-2.19
version-0.76
Compress-Raw-Zlib-2.012
IO-Compress-Base-2.012
Compress-Raw-Bzip2-2.012
IO-Compress-Bzip2-2.012
IO-Compress-Zlib-2.012
Compress-Zlib-2.012 (make install UNINST=1 - так как у нас этот модуль уже установлен, но версия не та, то ставим именно так)
IO-Zlib-1.09
Package-Constants-0.01
Archive-Tar-1.40
Pod-Simple-3.07
podlators-2.2.0
Regexp-Common-2.122
Pod-Readme-0.09
Test-Harness-2.62
PAR-Dist-0.40
Archive-Zip-1.26
Module-Build-0.30 (t/use_tap_harness.....skipped all skipped: TAP::Parser not installed говорит, хотя он есть в установленном модуле Test-Harness. Проигнорируем...)
Test-Distribution-1.24
Test-Portability-Files-0.05
Test-Taint-1.04
Readonly-1.03
Readonly-XS-1.04
Params-Validate-0.91
Time-modules-2006.0814
File-MMagic-1.27
MIME-Types-1.24
Module-Find-0.05
Sub-Uplevel-0.18
Array-Compare-1.16
Test-Exception-0.27
Tree-DAG_Node-1.06
Test-Warn-0.11
Archive-Any-0.0932
Class-Accessor-0.31
Algorithm-Diff-1.1902
Array-Diff-0.04
CPAN-DistnameInfo-0.06
File-Slurp-9999.13
IO-Capture-0.05
List-MoreUtils-0.22 (при установке ругнулся, что Test::Pod not installed, но я его ставил. Игнорируем, но держим в уме, что модуль проблемный)
Test-Tester-0.103
Test-NoWarnings-0.084
Test-Deep-0.103
UNIVERSAL-require-0.11
Pod-Strip-1.02
Parse-RecDescent-1.94
Module-ExtractUse-0.23
Module-Pluggable-2.96
Params-Util-0.33
Sub-Install-0.924
Data-OptList-0.103
Sub-Exporter-0.980
Data-Section-0.005 (распаковывать обязательно при помощи tar -xvzf)
Text-Template-1.45
Software-License-0.008
YAML-0.62
Devel-Leak-0.03
YAML-Syck-0.95
Test-YAML-Valid-0.03
Test-YAML-Meta-0.11
Text-CSV_XS-0.57
Module-CPANTS-Analyse-0.82 (make test работает очень долго. Это нормально)
Test-Kwalitee-1.01 (Как его проставить - ХЕЗ. makefile.PL отсутствует как класс. Делаем так. Сначала под alexsf выполняем perl Build.PL, потом под root копируем содержимое blib/lib в /usr/lib/perl5/site_perl/5.8.8, и Test::Kwalitee.3pm в /usr/share/man/man3)
POE-Component-Server-Syslog-1.16 (t/99_test_kwalitee....ok, значит предыдущий пакет поставлен правильно :) )
Sys-Syslog-0.27
Sub-Name-0.02
Sub-Identify-0.03
SUPER-1.16
Algorithm-C3-0.07
Class-C3-XS-0.07
Class-C3-0.19
Class-MOP-0.37
Test-LongString-0.11
Locale-US-1.2
Params-Coerce-0.14
Business-ISBN-Data-20081020
GD-Barcode-1.15
Business-ISBN-2.04 (сказал, что GD::Font не загружен. Такого не нашел. Игнорируем и ставим)
URI-1.37
IO-String-1.08
IO-stringy-2.110
DBM-Deep-1.0013 (ругнулся на несколько тестов, но игнорируем и ставим)
Test-Output-0.12 (ошибки игнорируем)
DateTime-Locale-0.41
Class-Singleton-1.03
DateTime-TimeZone-0.83 (Ругается, но ставим)
DateTime-0.4305 (некоторые тесты не прошли из-за отсутствия пакетов, которые проставлю дальше. Эти пакеты требуют, чтоб DateTime уже был установлен)
Set-Infinite-0.63
DateTime-Set-0.25
DateTime-Event-Recurrence-0.16
DateTime-Event-ICal-0.09
DateTime-Format-ICal-0.09
DateTime-Format-Strptime-1.0800
Class-Factory-Util-1.7
Task-Weaken-1.02
Test-Signature-1.10
DateTime-Format-HTTP-0.37
DateTime-Format-Mail-0.3001
DateTime-Format-IBeat-0.161
PadWalker-1.7
Devel-Cycle-1.10
Test-Memory-Cycle-1.04
DateTime-Format-Builder-0.7901
DateTime-Format-MySQL-0.04
Class-Inspector-1.23
aliased-0.22
Declare-Constraints-Simple-0.03
Moose-0.18
Mail-Sendmail-0.79 (ругается при тесте, что не может соединиться с сервером, но это нормально, игнорируем и ставим)
B-Keywords-1.08
Config-Tiny-2.12
Class-Data-Inheritable-0.08
Devel-StackTrace-1.12
Exception-Class-1.23
Module-Pluggable-3.1
Taint-Runtime-0.03
Clone-0.25
Scalar-List-Utils-1.19
Test-Object-0.07
PPI-1.203
String-Format-1.14
File-HomeDir-0.82
File-Which-0.05
Perl-Tidy-20071205
Pod-Spell-1.01
Regexp-Parser-0.20
Perl-Critic-1.092
Perl-Critic-Bangs-1.00 (на тесте ругается на некоторые вещи, но ставим все равно)
Perl-Critic-Lax-0.007
Test-Dynamic-1.3.3
DBD-Pg-1.49
Как этот модуль проверяется:
В pg_hba.conf меняем на:
#local all all ident sameuser
#host all all 127.0.0.1/32 ident sameuser
local all all password
host all all 127.0.0.1/32 password
host all all 0.0.0.0/0 password
Устанавливаем переменные окружения:
export DBI_PASS=postgres
export TEST_VERBOSE=1
export DBI_USER=postgres
export DBI_DSN='dbi:Pg:dbname=postgres'
И только после этого делаем make test. Потом возвращаем pg_hba.conf на место

Настраиваем postgres под Bucardo:

root# mkdir /u02
root# chown postgres:postgres /u02
root# su - postgres
postgres> mkdir /u02/pgdata/bucardo -p
postgres> psql
postgres=# CREATE USER bucardo SUPERUSER;
postgres=# ALTER ROLE bucardo password 'bucardo';
postgres=# CREATE TABLESPACE bucardo OWNER bucardo LOCATION '/u02/pgdata/bucardo';
postgres=# CREATE DATABASE bucardo WITH ENCODING='UTF8' OWNER=bucardo TABLESPACE=bucardo;
postgres=# CREATE LANGUAGE plperlu;
postgres=# \q
postgres> psql -h 10.77.11.207 -U bucardo bucardo
bucardo=# CREATE LANGUAGE plpgsql;
bucardo=# CREATE LANGUAGE plperlu;
bucardo=# \q
postgres> psql -f bucardo.schema -h 10.77.11.207 -U bucardo bucardo
bucardo=# \q

DBIx-Safe-1.2.4 - из самого bucardo
Bucardo-3.0.9 - из самого bucardo

Особенности установки Bucardo-3.0.9:

0. Во всех скриптах bucardo, исполняемых перловских файлах и т.д. неправильно стоит ссылка на perl, поэтому везде нужно поменять /usr/local/bin/perl на /usr/bin/perl. Я пока поменял только в bucardo_ctl, но и в остальных в будущем нужно будет это сделать.

1. Экспортируем переменные окружения:

export DBI_DSN='dbi:Pg:dbname=bucardo'
export DBI_USER=bucardo
export DBI_PASS=bucardo
export TEST_VERBOSE=1

2. PostgreSQL должен быть настроен на время теста на коннект к базе локальных соединений через пароль. То есть в pg_hba.conf первыми строками д.б.:

local all all password
host all all 127.0.0.1/32 password

3. Редактируем файл Bucardo-3.0.9/t/bucardo.test.data

## This file contains the connection information needed for "make test"

## Master database. This must be a superuser, as we will create a bucardo_test database
DBNAME: bucardo
DBUSER: bucardo
DBHOST: 10.77.11.207
DBPORT: 5432
TESTDB: bucardo_test
TESTBC: bucardo_test

## First database
DBNAME1: postgres
DBUSER1: bucardo
DBHOST1:
DBPORT1: 5432
TESTDB1: bucardo_test1
TESTBC1: bucardo_test1

## Second database:
DBNAME2: postgres
DBUSER2: bucardo
DBHOST2:
DBPORT2: 5432
TESTDB2: bucardo_test2
TESTBC2: bucardo_test2

## Third database:
DBNAME3: postgres
DBUSER3: bucardo
DBHOST3:
DBPORT3: 5432
TESTDB3: bucardo_test3
TESTBC3: bucardo_test3

После этого:

perl Makefile.PL
make
make test TEST_VERBOSE=1

Во время работы теста будут созданы тестовые БД, в них чего-то зальется и т.д. Ход всей работы будет на консоли. Будут ошибки, но я так предполагаю, что не критичные, так как в целом, как я понимаю, все отработало ОК. Поэтому под root make install.

Все. Проставили. Е**тня с модулями закончена...

Так. Теперь настраиваем bucardo. На моем хосте в postgresql есть созданная база bucardo, с такими же пользователем и паролем. логинимся в любой sql менеджер под bucardo и выполняем:

-- соединение с Новокаховской БД, которую нужно реплицировать
INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('nkres','10.77.12.4','nkres','nkres','вставляем_свой_пароль_на_nkres');

-- БД куда реплицировать
INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('allres','10.77.11.207','allres','allres','allres');

-- скорее всего это группа для РЭСовских БД
INSERT INTO bucardo.dbgroup (name) VALUES ('res_slaves');

-- ну тут понятно - ставим соответствие между БД и группами БД
INSERT INTO bucardo.dbmap (db, dbgroup) VALUES ('nkres','res_slaves');

-- настраиваем, какие таблицы реплицировать
-- тут нюанс. PK у нас везде double precision, но мы использовать этот тип не можем, поэтому
-- ставлю bigint, хотя не факт, что так заработает
INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('nkres','nkres','_bucardo_fio','id','bigint','false');
INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('nkres','nkres','_bucardo_cars','id','bigint','false');

-- создаем т.н. herd (группа объектов для репликации)
INSERT INTO bucardo.herd (name) VALUES ('nkres_test_bucardo');

-- запихиваем эти самые объекты в группу
INSERT INTO bucardo.herdmap (herd, goat)
SELECT 'nkres_test_bucardo', id
FROM goat WHERE db = 'nkres'

-- ну и собственно как откуда куда и как
INSERT INTO bucardo.sync (name,source,targetdb,synctype,stayalive,checktime,analyze_after_copy)
VALUES ('nkres','nkres_test_bucardo','allres','pushdelta','false','1 minutes','false')

Так, что-то не получается. Ругается, что не установлены языки на постгресе. Возможно эти языки д.б. установлены в новокаховской базе. Но она в промэксплуатации, поэтому эксперименты будем ставить на тестовой. Подробно:

В Н.Каховке делаем тестовую базу:

CREATE ROLE nkres_slave LOGIN ENCRYPTED PASSWORD 'md5ecc3ea090f168344b2a37be2c21ebc95'
NOINHERIT
VALID UNTIL 'infinity';

CREATE DATABASE nkres_slave
WITH ENCODING='UTF8'
OWNER=nkres_slave;

-- В базе nkres_slave
CREATE SCHEMA nkres_slave AUTHORIZATION nkres_slave;
CREATE LANGUAGE plpgsql;
CREATE LANGUAGE plperlu;

-- Логинимся под nkres_slave и делаем тестовые таблицы

CREATE TABLE nkres_slave._bucardo_cars
(id double precision NOT NULL,
car character varying(20),
nomer character varying(12),
CONSTRAINT pk__bucardo_cars PRIMARY KEY (id))
WITH (OIDS=FALSE);

CREATE TABLE _bucardo_fio
(id double precision NOT NULL,
fio character varying(100),
CONSTRAINT pk__bucardo_fio PRIMARY KEY (id))
WITH (OIDS=FALSE);

Чистим настройки bucardo в базе на 10.77.11.207:

delete from bucardo.sync;
delete from bucardo.herdmap;
delete from bucardo.herd;
delete from bucardo.goat;
delete from bucardo.dbmap;
delete from bucardo.dbgroup;
delete from bucardo.db;

Настраиваем БД bucardo:

-- Регистрируем БД Н.Каховки
INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('nkres_slave','10.77.12.4','nkres_slave','nkres_slave','nkres_slave');
-- Регистрируем локальную БД, куда будет сливаться всё
INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('allres','10.77.11.207','allres','allres','allres');

-- Создаем группы БД для sleves РЭСов и master конторы:
INSERT INTO bucardo.dbgroup(name) VALUES('res_slaves');
INSERT INTO bucardo.dbgroup(name) VALUES('obl_master');

-- Ставим соответствие между БД и группами БД
INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('nkres_slave','res_slaves');
INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('allres','obl_master');

-- Указываем, какие объекты из nkres_slave реплицировать
-- Тут нюанс. PK у нас везде double precision, но мы использовать этот тип не можем, поэтому
-- ставлю bigint, хотя не факт, что так заработает
INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('nkres_slave','nkres_slave','_bucardo_fio','id','bigint','false');
INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('nkres_slave','nkres_slave','_bucardo_cars','id','bigint','false');

-- Создаем группу объектов репликации
INSERT INTO bucardo.herd(name) VALUES('nkres_slave_herd');

-- Заносим таблицы в группу объектов репликации
INSERT INTO bucardo.herdmap (herd, goat)
SELECT 'nkres_slave_herd', id
FROM goat WHERE db = 'nkres_slave';

-- Настраиваем правила и пути репликации
INSERT INTO bucardo.sync (name,source,targetdb,synctype,stayalive,checktime,analyze_after_copy)
VALUES('nkres_slave_rep','nkres_slave_herd','allres','pushdelta','false','1 minutes','false');

И получаем:

NOTICE: Issuing rollback() for database handle being DESTROY'd without explicit disconnect() at line 29.

CONTEXT: SQL-команда: "SELECT validate_sync('nkres_slave_rep')"
ERROR: error from Perl trigger function: error from Perl function: No such table found for database allres: "nkres_slave._bucardo_cars" at line 259. at line 30.

********** Ошибка **********

ERROR: error from Perl trigger function: error from Perl function: No such table found for database allres: "nkres_slave._bucardo_cars" at line 259. at line 30.
SQL state: XX000

В базе nkres_slave появились объекты bucardo, на таблицах появились триггеры, но тем не менее ошибка. Что ту можно предположить? Возможно, так как bucardo не реплицирует DDL, то реплицируемые таблицы уже должны существовать в базе allres... Создаем пустые таблицы в allres и пробуем опять.

Нет, не помогло. Та же ошибка. Может нужен herd для базы allres??? А может, что совсем плохо, базы и схемы должны называться одинаково???

Итак, в базе allres делаем схему nkres_slave, а в нец создаем таблицы:

CREATE TABLE nkres_slave._bucardo_cars
( id double precision NOT NULL,
car character varying(20),
nomer character varying(12),
CONSTRAINT pk__bucardo_cars PRIMARY KEY (id)
) WITH (OIDS=FALSE);

CREATE TABLE nkres_slave._bucardo_fio
( id double precision NOT NULL,
fio character varying(100),
CONSTRAINT pk__bucardo_fio PRIMARY KEY (id)
) WITH (OIDS=FALSE);

После этого в bucardo

INSERT INTO bucardo.sync (name,source,targetdb,synctype,stayalive,checktime,analyze_after_copy)
VALUES('nkres_slave_rep','nkres_slave_herd','allres','pushdelta','false','1 minutes','false');

Запрос отработал. Итак, что имеем... А имеем херню - нужно чтоб во всех РЭСах схемы назывались одинаково... Ладно, с этим позже разберемся...

Теперь нужно запустить bucardo. Для этого есть скриптец bucardo_ctl
Для начала отредактируем его, пропишем корректные пароли и пользователей. А потом пытаемся запустить. Для этого ту папку, из которой ставили модуль bucardo копируем в opt, получаем папку

/opt/Bucardo-3.0.9

Там редактируем bucardo_ctl. Устанавливаем секцию

my $bcargs = {
ctlquiet => 0,
ctlverbose => 0,
dbname => 'bucardo',
dbuser => 'bucardo',
dbpass => 'bucardo_bucardo',
verbose => 1, ## Highly recommended to leave this on
sendmail => 0,
extraname => '',
debugfilesep => 0,
debugname => '',
debugstderr => 0,
debugstdout => 0,
debugsyslog => 1,
debugdir => '',
debugfile => 0,
cleandebugs => 1,
};

Кроме того, в первой строке устанавливаем правильный интерпретатор, то есть меняем
/usr/local/bin/perl на /usr/bin/perl

То же самое делаем с скриптами:

./scripts/bucardo_ctl.rc
./scripts/bucardo-report
./scripts/bucardo_rrd
./scripts/check_bucardo_sync
Bucardo.pm
/usr/lib/perl5/site_perl/5.8.8

Ну и пытаемся запустить:

./bucardo_ctl start "Test start - test"

Получаем

Checking for existing processes
Line 716: Could not open "/home/bucardo/restart.reason": Нет такого файла или каталога

Интересно... Предполагается, что б.д. локальный пользователь bucardo. Делаем его

root# useradd -c "Bucardo Replication" -d /home/bucardo -p bucardo_bucardo -s /bin/bash bucardo
root# mkdir /home/bucardo
root# chown bucardo /home/bucardo

Пытаемся запустить опять:

./bucardo_ctl start "Test start - test"

Получаем

Checking for existing processes
Line 727: Could not create "/var/run/bucardo/fullstopbucardo": Нет такого файла или каталога

Под root делаем:

root# mkdir /var/run/bucardo
root# chown bucardo /var/run/bucardo

Пытаемся запустить опять, получаем:

Checking for existing processes
Removing /var/run/bucardo/fullstopbucardo
Starting Bucardo

То есть типа bucardo стартовал...

Настроим логирование, чтоб легче ьыло анализировать работу...
Редактируем /etc/syslog-ng/syslog-ng.conf.in. Добавляем туда:

filter f_bucardo {match('ucardo');};
destination d_bucardo {file(/var/log/bucardo/bucardo);};
log {source(src);filter(f_bucardo);destination(d_bucardo);};

Потом под root выполняем

root# mkdir /var/log/bucardo
root# chown bucardo /var/log/bucardo
root# SuSEconfig
root# /etc/init.d/syslog restart

Останавливаем и запускаем bucardo для проверки...

./bucardo_ctl stop "Test stop"
./bucardo_ctl start "test start"

Проверяем, чреплицировалось что-нибудь или нет???
Нет. В базе allres таблицы nkres_slave._bucardo_cars и nkres_slave._bucardo_fio не изменились... Почему??? Возможно потому, что у меня стоит тип репликации pushdelta.

Pushdelta - A type of sync in which the changes to a source are replicated to a target. То есть так как после запуска репликации я не менял содержимое таблиц, то ничего и не произошло...
Возможно нужно выполнить для начала репликацию fullcopy

Fullcopy - A type of sync in which the target is truncated and the entire source is replicated to it.

, а потом уже переключиться на pushdelta

Пробуем: меняем в bucardo.sync pushdelta на fullcopy и перезапускаем bucardo.

./bucardo_ctl stop "Stop pushdelta -> fullcopy"
./bucardo_ctl start "Start pushdelta -> fullcopy"

И ничего... Смотрим логи bucardo, и видим:

Nov 10 11:53:37 vmsles10 Bucardo[13683]: KID Warning! Child for "nkres_slave_rep" was killed at line 3822: DBD::Pg::db do failed: ERROR: доступ запрещён для связи pg_class main error: none source error: none target error: 7

Блин. Проверил, у всех ролей, вовлеченных в процесс доступ к pg_class есть... Что за фигня??? Варианта два. 1 - у кого-то нехватает прав. 2 - другой вариант :) Пытаемся проверить вариант 1. Всем участникам процесса даем роль SUPERUSER (allres, nkres_slave)

Мля, получилось.... Появились данные...

Ставим режим репликации на pushdelta, перезапускаем и пробуем манипулировать данными.
Работает. Причем мгновенно :) Радует.

Пробуем 2-ю БД добавить. На сервере 10.77.11.52 клепаем БД bucardo_res, и создаем 2 любимые таблицы в ней. И добавляем все это в конфигурацию bucardo

INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('bucardo_res','10.77.11.52','bucardo_res','bucardo_res','bucardo_res');

INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('bucardo_res','res_slaves');

INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('bucardo_res','nkres_slave','_bucardo_fio','id','bigint','false');

INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('bucardo_res','nkres_slave','_bucardo_cars','id','bigint','false');

INSERT INTO bucardo.herd(name) VALUES('bucardo_res_herd');

INSERT INTO bucardo.herdmap (herd, goat)
SELECT 'bucardo_res_herd', id
FROM goat WHERE db = 'bucardo_res';

INSERT INTO bucardo.sync (name,source,targetdb,synctype,stayalive,checktime,analyze_after_copy)
VALUES('bucardo_res_rep','bucardo_res_herd','allres','pushdelta','false','1 minutes','false');

При манипулировании данными выяснилось, таки что при pushdelta реплицируются только данные, измененные после запуска репликации. Пробуем fullcopy, а потом pushdelta. И вот тут мы натыкаемся на такую жопу. При fullcopy из таблиц БД allres были удалены все данные, и установлены те, которые находились в bucardo_res. А сие не есть гуд.

Вариант такой. Никогда не использовать fullcopy. Всегда pushdelta, но для того, чтобы все просинхронизировалось изначально, делаем какой-нибудь update на всех таблицах, который реально никаких данных не поменяет, но заставит bucardo провести синхронизаци.

Например

update nkres_slave._bucardo_cars set car = car

Проверил, работает.

Теперь проверим на рабочих базах в тестовом варианте.
Итак на сервере 10.77.11.52 создали 2 БД, cpres и klres, залили в них резервные копии, так что в каждой БД появились схемы cpres и klres соответственно. Естественно перед этим были созданы табличные пространства и пользователи, хозяева БД и схем. После это в каждой БД переименовываем схемы на res. Затем создаем локальную БД (куда будет реплицироваться), называем ее fullres, хозяином делаем пользователя res, и в ней делаем схему res. Напоминаю, что все пользователи, участвующие в процессе д.б. SUPERUSER. После этого нам необходимо в схеме res в БД fullres создать идентичные объекты БД. Потом не забываем создать языки plpgsql и plperlu.

Теперь приступим к настройкам bucardo. У нас в каждой БД 300 с гаком таблиц, которые д.б идентичны по структуре. Нужно немного автоматизировать процесс. Итак.

delete from bucardo.sync;
delete from bucardo.herdmap;
delete from bucardo.herd;
delete from bucardo.goat;
delete from bucardo.dbmap;
delete from bucardo.dbgroup;
delete from bucardo.db;

INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('klres','10.77.11.52','klres','klres','klres_klres_klres');

INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('cpres','10.77.11.52','cpres','cpres','cpres_cpres_cpres');

INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('fullres','10.77.11.207','fullres','res','res_res');

INSERT INTO bucardo.dbgroup(name) VALUES('res_slaves');
INSERT INTO bucardo.dbgroup(name) VALUES('res_master');

INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('klres','res_slaves');
INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('cpres','res_slaves');
INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('fullres','res_master');

Для ввода данных в таблицу goat используем след. запрос. Мы его выполняем в klres, а результаты в bucardo.

select 'insert into bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy) VALUES (''klres'',''res'','''||cl.relname||''','''||con.conname||''',''bigint'',''false'');'
from pg_constraint con, pg_class cl, pg_tables t
where t.schemaname = 'res'
and t.tablename = cl.relname
and con.contype = 'p'
and con.conrelid = cl.oid

И оказалось, что таблиц 389, а первичных ключей всего 386. То есть где-то нету PK. Нужно найти и либо поставить PK, либо эту таблицу не реплицировать.

Засранцев ловим таким образом:

select distinct t.tablename
from pg_tables t, pg_class cl, pg_constraint con
where t.schemaname = 'res'
and t.tablename = cl.relname
and t.tablename not in (select cl.relname
from pg_constraint con, pg_class cl
where contype = 'p'
and con.conrelid = cl.oid)

Пойманные засранцы оказались временными и в репликации участия не принимают. Но в будущем наличие PK все равно нужно проверять. Указанный выше запрос используем для вставки данных в таблицу goat для klres и cpres. Не забываем в запросе менять klres и cpres.

INSERT INTO bucardo.herd(name) VALUES('klres_herd');
INSERT INTO bucardo.herd(name) VALUES('cpres_herd');

INSERT INTO bucardo.herdmap (herd, goat)
SELECT 'klres_herd', id
FROM goat WHERE db = 'klres';

INSERT INTO bucardo.herdmap (herd, goat)
SELECT 'cpres_herd', id
FROM goat WHERE db = 'cpres';

Ну и последний штрих:

INSERT INTO bucardo.sync (name,source,targetdb,synctype,stayalive,checktime,analyze_after_copy)
VALUES('klres','klres_herd','fullres','pushdelta','false','30 minutes','false');

INSERT INTO bucardo.sync (name,source,targetdb,synctype,stayalive,checktime,analyze_after_copy)
VALUES('cpres','cpres_herd','fullres','pushdelta','false','30 minutes','false');

Так. отработало... Уф, аж вспотел...

Ну и не менее ответственный шаг - перезапуск bucardo, и пинок в задницу в виде ничего не значащено update по всем таблицам в реплицируемых схемах...

Bucardo перезапустили. Ошибок в логах нет, и синхронизации нет. Нужен костыль для пинка. Пишем...

--select con.conname, cc.column_name, cc.constraint_schema, con.contype, cl.relname
select 'update res.'||cl.relname||' set '||cc.column_name||'='||cc.column_name||';'
from pg_constraint con, information_schema.constraint_column_usage cc, pg_tables t, pg_class cl
where con.conname = cc.constraint_name
and con.contype = 'p'
and con.conrelid = cl.oid
and t.tablename = cl.relname
order by cl.relname

Пытаюсь выполнить результат и получаю ошибку:

ERROR: record "old" has no field "pk_act"
CONTEXT: PL/pgSQL function "bucardo_add_delta_u_pk_act" line 3 at SQL statement

Фиг его знает, что такое. Наверное щас все в bucardo нафиг выкошу и попробую поставить только одну таблицу, посмотрб, что получится. Возможно при массовом добавлении закралась какая-то ошибка...

delete from bucardo.sync;
delete from bucardo.herdmap;
delete from bucardo.herd;
delete from bucardo.goat;
delete from bucardo.dbmap;
delete from bucardo.dbgroup;
delete from bucardo.db;

INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('klres','10.77.11.52','klres','klres','klres_klres_klres');

INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('fullres','10.77.11.207','fullres','res','res_res');

INSERT INTO bucardo.dbgroup(name) VALUES('res_slaves');
INSERT INTO bucardo.dbgroup(name) VALUES('res_master');

INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('klres','res_slaves');
INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('fullres','res_master');

insert into bucardo.goat(db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('klres','res','act','pk_act','bigint','false');

INSERT INTO bucardo.herd(name) VALUES('klres_herd');

INSERT INTO bucardo.herdmap (herd, goat)
SELECT 'klres_herd', id
FROM goat WHERE db = 'klres';

INSERT INTO bucardo.sync (name,source,targetdb,synctype,stayalive,checktime,analyze_after_copy)
VALUES('klres','klres_herd','fullres','pushdelta','false','5 minutes','false');

При попытке сделать пинок получил то же самое, ошибку.

################################################################

res (10.77.11.207)

CREATE LANGUAGE plpgsql;
CREATE LANGUAGE plperlu;

CREATE TABLE res._bucardo_cars
( id double precision NOT NULL,
car character varying(20),
nomer character varying(12),
CONSTRAINT pk__bucardo_cars PRIMARY KEY (id)
) WITH (OIDS=FALSE);

CREATE TABLE res._bucardo_fio
( id double precision NOT NULL,
fio character varying(100),
CONSTRAINT pk__bucardo_fio PRIMARY KEY (id)
) WITH (OIDS=FALSE);

res (10.77.11.52)

CREATE LANGUAGE plpgsql;
CREATE LANGUAGE plperlu;

CREATE TABLE res._bucardo_cars
( id double precision NOT NULL,
car character varying(20),
nomer character varying(12),
CONSTRAINT pk__bucardo_cars PRIMARY KEY (id)
) WITH (OIDS=FALSE);

CREATE TABLE res._bucardo_fio
( id double precision NOT NULL,
fio character varying(100),
CONSTRAINT pk__bucardo_fio PRIMARY KEY (id)
) WITH (OIDS=FALSE);

klres (10.77.11.52)

CREATE TABLE res._bucardo_cars
( id double precision NOT NULL,
car character varying(20),
nomer character varying(12),
CONSTRAINT pk__bucardo_cars PRIMARY KEY (id)
) WITH (OIDS=FALSE);

CREATE TABLE res._bucardo_fio
( id double precision NOT NULL,
fio character varying(100),
CONSTRAINT pk__bucardo_fio PRIMARY KEY (id)
) WITH (OIDS=FALSE);

bucardo(10.77.11.207)

delete from bucardo.sync;
delete from bucardo.herdmap;
delete from bucardo.herd;
delete from bucardo.goat;
delete from bucardo.dbmap;
delete from bucardo.dbgroup;
delete from bucardo.db;

INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('slave_res_52','10.77.11.52','res','res','res');
INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('slave_klres_res_52','10.77.11.52','klres','klres','klres_klres_klres');
INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('master_res','10.77.11.207','res','res','res_res');

INSERT INTO bucardo.dbgroup(name) VALUES('slaves_res');
INSERT INTO bucardo.dbgroup(name) VALUES('master_obl');

INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('slave_res_52','slaves_res');
INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('slave_klres_res_52','slaves_res');
INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('master_res','master_obl');

INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('slave_res_52','res','_bucardo_fio','id','bigint','false');
INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('slave_res_52','res','_bucardo_cars','id','bigint','false');
INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('slave_klres_res_52','res','_bucardo_fio','id','bigint','false');
INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('slave_klres_res_52','res','_bucardo_cars','id','bigint','false');

INSERT INTO bucardo.herd(name) VALUES('herd_res_52');
INSERT INTO bucardo.herd(name) VALUES('herd_klres_res_52');

INSERT INTO bucardo.herdmap (herd, goat)
SELECT 'herd_res_52', id
FROM goat WHERE db = 'slave_res_52';
INSERT INTO bucardo.herdmap (herd, goat)
SELECT 'herd_klres_res_52', id
FROM goat WHERE db = 'slave_klres_res_52';

INSERT INTO bucardo.sync (name,source,targetdb,synctype,stayalive,checktime,analyze_after_copy)
VALUES('sync_res_52','herd_res_52','master_res','pushdelta','false','5 minutes','false');
INSERT INTO bucardo.sync (name,source,targetdb,synctype,stayalive,checktime,analyze_after_copy)
VALUES('sync_klres_res_52','herd_klres_res_52','master_res','pushdelta','false','5 minutes','false');

root(10.77.11.207 ssh)

./bucardo_ctl start 'New'

Дальше в каждой схеме делаем пинок, как описано выше.

В логах bucardo после этого имеем:

Nov 25 09:19:41 vmsles10 Bucardo[7286]: KID Warning! Child for "sync_res_52" was killed at line 3822: DBD::Pg::db do failed: ERROR: доступ запрещён для связи pg_class main error: none source error: none target error: 7
Nov 25 09:19:42 vmsles10 Bucardo[7289]: KID Warning! Child for "sync_klres_res_52" was killed at line 3822: DBD::Pg::db do failed: ERROR: доступ запрещён для связи pg_class main error: none source error: none target error: 7

Непонимайу!!! Все юзеры суперюзеры!!! По крайней мере через pgAdmin. Даем руками:

alter role res superuser;
alter role klres superuser;

Оппачки. А так работает. Так что суперюзеров давать ТОЛЬКО РУКАМИ!!!

Так, пытаемся добавить одну из рабочих таблиц схемы klres, на которой не работала репликация...

res(10.77.11.207)

CREATE TABLE res.act
(
code double precision NOT NULL,
"name" character varying(50),
dategen timestamp with time zone NOT NULL,
"content" character varying(100),
valuekwt double precision NOT NULL,
calcvalue double precision NOT NULL,
startdate timestamp with time zone NOT NULL,
enddate timestamp with time zone NOT NULL,
isincourt double precision NOT NULL,
topayvalue double precision NOT NULL,
recordpontrfcode double precision NOT NULL,
statuscode double precision NOT NULL,
thefttypecode double precision NOT NULL,
modify_time double precision,
domain_info character varying(100) NOT NULL,
agreedpower double precision,
receptioncapacty double precision,
hoursusageperday double precision,
summrprdstrtmnth double precision,
summerperdstrtdy double precision,
wintrprdstrtmnth double precision,
winterperdstrtdy double precision,
changingdate timestamp with time zone,
blanknumber character varying(50) NOT NULL,
considerationdat timestamp with time zone,
verdict text,
formula text,
phases double precision,
commissionformula text,
coordinatedtypecode double precision,
coordinatedtypedate date,
CONSTRAINT pk_act PRIMARY KEY (code)
)
WITH (OIDS=FALSE);

bucardo(10.77.11.207)

INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('slave_klres_res_52','res','act','code','bigint','false');

root(10.77.11.207 ssh)

./bucardo_ctl stop 'add Act'
./bucardo_ctl start 'add Act'

Делаем пинок таблицы act

klres(10.77.11.52)

update res.act set code=code;

И получаем:

ERROR: record "old" has no field "pk_act"
CONTEXT: PL/pgSQL function "bucardo_add_delta_u_pk_act" line 3 at SQL statement
********** Ошибка **********
ERROR: record "old" has no field "pk_act"
SQL state: 42703
Контекст:PL/pgSQL function "bucardo_add_delta_u_pk_act" line 3 at SQL statement

Блин. Это при том, что

update res._bucardo_cars set id=id
update res._bucardo_fio set id=id

работает... Где провтык???

Порылся, и заметил замечательную закономерность. На таблице _bicardo_cars в триггере bucardo_add_delta_u ссылка на процедуру bucardo.bucardo_add_delta_u_id(), а в act на процедуру bucardo.bucardo_add_delta_u_pk_act(). Обратите внимание, что в первом случае в имени процедуры указано поле первичного ключа, а во втором случае имя первичного ключа... Возможно, в этом проблема... Варианты???

Возможно code зарезервировано для служебных целей... Пробуем:

bucardo(10.77.11.207)

delete from bucardo.goat where tablename = 'act';
INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('slave_klres_res_52','res','act','"code"','bigint','false');

root(10.77.11.207 ssh)

./bucardo_ctl stop 'add Act code'
./bucardo_ctl start 'add Act code'

Пинок:

klres(10.77.11.52)

update res.act set code=code;

Блин. То же самое. Как вариант удалить объекты bucardo связанные с таблицей act в klres и заново сделать конфигурацию для этой таблицы...

bucardo(10.77.11.207)

delete from bucardo.goat where tablename = 'act';

klres(10.77.11.52)

DROP TRIGGER bucardo_add_delta_d ON res.act;
DROP TRIGGER bucardo_add_delta_i ON res.act;
DROP TRIGGER bucardo_add_delta_u ON res.act;
DROP TRIGGER bucardo_triggerkick_klres ON res.act;
DROP FUNCTION bucardo.bucardo_add_delta_d_pk_act();
DROP FUNCTION bucardo.bucardo_add_delta_i_pk_act();
DROP FUNCTION bucardo.bucardo_add_delta_u_pk_act();

bucardo(10.77.11.207)

INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('slave_klres_res_52','res','act','"code"','bigint','false');

Самое интересное - триггера на таблице не появились. Наверное это происходит в другой момент... Ищем в какой...

delete from bucardo.sync where name = 'sync_klres_res_52';

INSERT INTO bucardo.sync (name,source,targetdb,synctype,stayalive,checktime,analyze_after_copy)
VALUES('sync_klres_res_52','herd_klres_res_52','master_res','pushdelta','false','5 minutes','false');

Нет, ничего. Перезапустим bucardo...

Ничего... Так. Нужно найти, как вычистить все объекты bucardo в схеме klres и завести все заново...

root(10.77.11.207)

./bucardo_ctl stop 'drop bucardo from klres'

klres(10.77.11.52)

drop schema bucardo cascade;

Вроде так. Все триггера с таблиц уехали, и схема тоже... Теперь:

bucardo(10.77.11.207)

delete from bucardo.sync where name = 'sync_klres_res_52';
delete from bucardo.herdmap where herd = 'herd_klres_res_52';
delete from bucardo.herd where name = 'herd_klres_res_52';
delete from bucardo.goat where db = 'slave_klres_res_52';
delete from bucardo.dbmap where db = 'slave_klres_res_52';
delete from bucardo.db where name = 'slave_klres_res_52';

Мда, погорячился я... Схему bucardo в klres можно было выносить только после удаления всего klres-овского хозяйства из таблиц bucardo...

delete from bucardo.sync where name = 'sync_klres_res_52';
delete from bucardo.herd where name = 'herd_klres_res_52';

не отработали. Ругаются, блин...

Ну да ладно. Руками некоторые объекты bucardo в klres посоздавал по аналогии с cpres, и все получилось. Теперь заново настраиваем:

INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('slave_klres_res_52','10.77.11.52','klres','klres','klres_klres_klres');

INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('slave_klres_res_52','slaves_res');

INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('slave_klres_res_52','res','_bucardo_fio','id','bigint','false');
INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('slave_klres_res_52','res','_bucardo_cars','id','bigint','false');
INSERT INTO bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy)
VALUES ('slave_klres_res_52','res','act','code','bigint','false');

INSERT INTO bucardo.herd(name) VALUES('herd_klres_res_52');

INSERT INTO bucardo.herdmap (herd, goat)
SELECT 'herd_klres_res_52', id
FROM goat WHERE db = 'slave_klres_res_52';

INSERT INTO bucardo.sync (name,source,targetdb,synctype,stayalive,checktime,analyze_after_copy)
VALUES('sync_klres_res_52','herd_klres_res_52','master_res','pushdelta','false','5 minutes','false');

Во-о-о-о-о-о!!! Теперь похоже на правду. По крайней мере триггера сделаны по одному принципу.
Запускаем bucardo и раздаем пинки...

Пинки прошли удачно!!! Данные пошли!!!

Так, пробуем опять сделать все на рабочей схеме 2-х РЭСов - cpres, klres

######################################################################

bucardo(10.77.11.207)

delete from bucardo.sync;
delete from bucardo.herdmap;
delete from bucardo.herd;
delete from bucardo.goat;
delete from bucardo.dbmap;
delete from bucardo.dbgroup;
delete from bucardo.db;

Потом в klres и cpres выносим схемы bucardo

res(10.77.11.207)

drop schema res cascade;
CREATE SCHEMA res AUTHORIZATION res;

В схеме res создаем такие-же объекты, как в klres. дальше:

bucardo(10.77.11.207):

INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('slave_cpres','10.77.11.52','cpres','cpres','cpres_cpres_cpres');
INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('slave_klres','10.77.11.52','klres','klres','klres_klres_klres');
INSERT INTO bucardo.db (name, dbhost, dbname, dbuser, dbpass)
VALUES ('master_res','10.77.11.207','res','res','res_res');

INSERT INTO bucardo.dbgroup(name) VALUES('slaves_res');
INSERT INTO bucardo.dbgroup(name) VALUES('master_obl');

INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('slave_klres','slaves_res');
INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('slave_cpres','slaves_res');
INSERT INTO bucardo.dbmap(db, dbgroup) VALUES('master_res','master_obl');

А вот и ошибка. Для вставки данных в goat я использовал запрос

select 'insert into bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy) VALUES (''klres'',''res'','''||cl.relname||''','''||con.conname||''',''bigint'',''false'');'
from pg_constraint con, pg_class cl, pg_tables t
where t.schemaname = 'res'
and t.tablename = cl.relname
and con.contype = 'p'
and con.conrelid = cl.oid;

В данном запросе вместо поля PK используется его имя. Вот почему и не работало... Исправляем запрос:

select 'insert into bucardo.goat (db, schemaname,tablename,pkey,pkeytype,analyze_after_copy) VALUES (''slave_klres'',''res'','''
||cl.relname||''','''||cc.column_name||''',''bigint'',''false'');'
from pg_constraint con, pg_class cl, pg_tables t, information_schema.constraint_column_usage cc
where t.schemaname = 'res'
and t.tablename = cl.relname
and con.contype = 'p'
and con.conrelid = cl.oid
and cc.constraint_name = con.conname;

Естественно имя базы для каждого варианта свое...

Кстати, обнаружил, что на одной из таблиц PK был составной. Такого быть не должно. Только из одного поля.

INSERT INTO bucardo.herd(name) VALUES('herd_klres');
INSERT INTO bucardo.herd(name) VALUES('herd_cpres');

INSERT INTO bucardo.herdmap (herd, goat)
SELECT 'herd_klres', id
FROM goat WHERE db = 'slave_klres';
INSERT INTO bucardo.herdmap (herd, goat)
SELECT 'herd_cpres', id
FROM goat WHERE db = 'slave_cpres';

INSERT INTO bucardo.sync (name,source,targetdb,synctype,stayalive,checktime,analyze_after_copy)
VALUES('sync_cpres','herd_cpres','master_res','pushdelta','false','5 minutes','false');
INSERT INTO bucardo.sync (name,source,targetdb,synctype,stayalive,checktime,analyze_after_copy)
VALUES('sync_klres','herd_klres','master_res','pushdelta','false','5 minutes','false');

Запускаем bucardo, пинки, и о чудо, репликация пошла!!!

Но есть несколько но...
Различные ограничения, связанные с уникальностью и к требованию, например, конкрентых значений данных в столбцах... Это все нужно ловить через логи и стыковаться с программистами...


Читать далее

2008-10-14

PostgreSQL в РЭСах

=============================================================

1. Устанавливаем PostgreSQL на linux из rpm

rpm -ivh postgre*

=============================================================

2. Ставим Postgres на автозапуск


Обязательно нужно следить за тем, чтобы postgres стартовал после
oracle, или если oracle нет, то обязательно нужно выставить
правильные параметры ядра!!!

ln -s /etc/init.d/postgresql /etc/init.d/rc5.d/K11postgresql
ln -s /etc/init.d/postgresql /etc/init.d/rc5.d/S15postgresql
ln -s /etc/init.d/postgresql /etc/init.d/rc3.d/K11postgresql
ln -s /etc/init.d/postgresql /etc/init.d/rc3.d/S15postgresql

=============================================================

3. Меняем пароль postgres в БД

linux01:~ # su - postgres
postgres@linux01:~> psql
Welcome to psql 8.2.5, the PostgreSQL interactive terminal.

Type: \copyright for distribution terms
\h for help with SQL commands
\? for help with psql commands
\g or terminate with semicolon to execute query
\q to quit

postgres=# alter role postgres password 'postgres_postgres';
ALTER ROLE
postgres=# \q
postgres@linux01:~> exit
logout
linux01:~ #

=============================================================

4. Меняем содержимое конфигов Postgres

/var/lib/pgsql/data/pg_hba.conf

local all all ident sameuser
host all all 127.0.0.1/32 ident sameuser
host all all 0.0.0.0/0 password

/var/lib/pgsql/data/postgresql.conf

#------------------------------------------------------------------------------
# FILE LOCATIONS
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# CONNECTIONS AND AUTHENTICATION
#------------------------------------------------------------------------------
listen_addresses = '*'
max_connections = 100
superuser_reserved_connections = 5
#------------------------------------------------------------------------------
# RESOURCE USAGE (except WAL)
#------------------------------------------------------------------------------
max_fsm_pages = 153600
max_stack_depth = 2MB
shared_buffers = 500MB
temp_buffers = 30MB
work_mem = 5MB
#------------------------------------------------------------------------------
# WRITE AHEAD LOG
#------------------------------------------------------------------------------
fsync = off
#------------------------------------------------------------------------------
# QUERY TUNING
#------------------------------------------------------------------------------
constraint_exclusion = on
#------------------------------------------------------------------------------
# ERROR REPORTING AND LOGGING
#------------------------------------------------------------------------------
log_line_prefix = '%s %h %u '
log_min_duration_statement = 60000
log_min_error_statement = warning
redirect_stderr = on
#------------------------------------------------------------------------------
# RUNTIME STATISTICS
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# AUTOVACUUM PARAMETERS
#------------------------------------------------------------------------------
autovacuum = off
#------------------------------------------------------------------------------
# CLIENT CONNECTION DEFAULTS
#------------------------------------------------------------------------------
datestyle = 'iso, dmy'
lc_messages = 'ru_RU.UTF-8'
lc_monetary = 'ru_RU.UTF-8'
lc_numeric = 'ru_RU.UTF-8'
lc_time = 'ru_RU.UTF-8'
#------------------------------------------------------------------------------
# LOCK MANAGEMENT
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# VERSION/PLATFORM COMPATIBILITY
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# CUSTOMIZED OPTIONS
#------------------------------------------------------------------------------

=============================================================

5. Создаем все что нужно для РЭСа в БД

linux01:~ # mkdir /u02/pgdata/kvres -p
linux01:~ # chown postgres:postgres /u02/pgdata/kvres

Ну и под postgres в любой psql консоли (psql, pgAdmin, EMS, Navicat...)

CREATE ROLE kvres LOGIN ENCRYPTED PASSWORD 'md519ad6b2da7f7bf9f2994481e06047f1b'
NOINHERIT
VALID UNTIL 'infinity';

CREATE TABLESPACE kvres OWNER kvres LOCATION '/u02/pgdata/kvres';

CREATE DATABASE kvres
WITH ENCODING='UTF8'
OWNER=kvres
TABLESPACE=kvres;

-- И в базе kvres делаем схему
CREATE SCHEMA kvres AUTHORIZATION kvres;

=============================================================

6. Настраиваем vacuum & analyze

linux01:~ # mkdir /u02/scheduler/analyze/pgsql/ -p
linux01:~ # touch /u02/scheduler/analyze/pgsql/pgsql.sh
linux01:~ # touch /u02/scheduler/analyze/pgsql/analyze.sql
linux01:~ # touch /u02/scheduler/analyze/pgsql/vacuum.sql
linux01:~ # chown postgres:postgres /u02/scheduler/analyze/pgsql/ -R
linux01:~ # chmod ug+x /u02/scheduler/analyze/pgsql/pgsql.sh


Содержимое /u02/scheduler/analyze/pgsql/pgsql.sh:

#!/bin/bash
su - postgres -c "cd /u02/scheduler/analyze/pgsql; psql -d kvres -f vacuum.sql -o vacuum_execute -t; psql -d nkres -f vacuum_execute -o vacuum_execute.log"
su - postgres -c "cd /u02/scheduler/analyze/pgsql; psql -d kvres -f analyze.sql -o analyze_execute -t; psql -d nkres -f analyze_execute -o analyze_execute.log"

/u02/scheduler/analyze/pgsql/analyze.sql

select 'analyze verbose ' || table_schema || '.' || table_name || ';'
from information_schema.tables
where lower(table_schema) = 'kvres'
and lower(table_type) = 'base table'
order by table_schema, table_name;

/u02/scheduler/analyze/pgsql/vacuum.sql

select 'vacuum full verbose ' || table_schema || '.' || table_name || ';'
from information_schema.tables
where lower(table_schema) = 'kvres'
and lower(table_type) = 'base table'
order by table_schema, table_name;

=============================================================

7. Настраиваем резервное копирование

linux01:~ # mkdir /u02/scheduler/backup/pgsql/ -p
linux01:~ # touch /u02/scheduler/backup/pgsql/pgsql.sh
linux01:~ # chmod ug+x /u02/scheduler/backup/pgsql/pgsql.sh

Содержимое /u02/scheduler/backup/pgsql/pgsql.sh:

#!/bin/bash
export CURDT=$(date +%Y-%m-%d.%H.%M.%S)
mkdir data
mkdir mountpoint
chown postgres:postgres data
chown postgres:postgres mountpoint

su - postgres -c "cd /u02/scheduler/backup/pgsql/data; pg_dump -C -F c -b -f pgsql.kvres "kvres""
tar -cvzf data/pgsql.kvres.$CURDT.tar.gz data/pgsql.kvres
rm data/pgsql.kvres
umount mountpoint
umount mountpoint
umount mountpoint
umount mountpoint
umount mountpoint
umount mountpoint
umount mountpoint
umount mountpoint
#mount 10.77.44.3:/files/backup/pgsql mountpoint -w
/usr/bin/smbmount \\\\10.77.42.113\\Backup mountpoint -o username=linux,password=linux,rw
cp -fv data/pgsql.kvres.$CURDT.tar.gz mountpoint\pgsql
umount mountpoint
umount mountpoint
umount mountpoint
umount mountpoint
umount mountpoint
umount mountpoint
umount mountpoint
umount mountpoint

=============================================================

8. Добавляем в планировщик.
То есть в tasks.sh добавляем:

###############################
# Backup PostgreSQL databases #
###############################
cd /u02/scheduler/backup/pgsql
./pgsql.sh
#############################
# VACUUL+ANALYZE postgresql #
#############################
cd /u02/scheduler/analyze/pgsql
./pgsql.sh

=============================================================

9. Делаем пользователя только на чтение

-- Под пользователем postgres
CREATE ROLE "read_ber" NOINHERIT LOGIN PASSWORD 'read_ber';
-- Под пользователем kvres
GRANT USAGE
ON SCHEMA "kvres" TO "read_ber";


Читать далее

2008-10-06

Базовая настройка PostgreSQL 8.2.5 на linux

Базовая настройка PostgreSQL 8.2.5 на SLES9 и SLES10

/var/lib/pgsql/data/pg_hba.conf выглядит так:

local all all ident sameuser
host all all 127.0.0.1/32 ident sameuser
host all all 0.0.0.0/0 password

/var/lib/pgsql/data/postgresql.conf выглядит так:


#------------------------------------------------------------------------------
# FILE LOCATIONS
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# CONNECTIONS AND AUTHENTICATION
#------------------------------------------------------------------------------
listen_addresses = '*'
max_connections = 100
superuser_reserved_connections = 5
#------------------------------------------------------------------------------
# RESOURCE USAGE (except WAL)
#------------------------------------------------------------------------------
max_fsm_pages = 153600
max_stack_depth = 2MB
shared_buffers = 500MB
temp_buffers = 30MB
work_mem = 5MB
#------------------------------------------------------------------------------
# WRITE AHEAD LOG
#------------------------------------------------------------------------------
fsync = off
#------------------------------------------------------------------------------
# QUERY TUNING
#------------------------------------------------------------------------------
constraint_exclusion = on
#------------------------------------------------------------------------------
# ERROR REPORTING AND LOGGING
#------------------------------------------------------------------------------
#log_error_verbosity = verbose
#log_duration = on
log_line_prefix = '%s %h %u '
log_min_duration_statement = 60000
log_min_error_statement = warning
#log_statement = 'ddl'
redirect_stderr = on
#------------------------------------------------------------------------------
# RUNTIME STATISTICS
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# AUTOVACUUM PARAMETERS
#------------------------------------------------------------------------------
autovacuum = off
#------------------------------------------------------------------------------
# CLIENT CONNECTION DEFAULTS
#------------------------------------------------------------------------------
datestyle = 'iso, dmy'
lc_messages = 'ru_RU.UTF-8'
lc_monetary = 'ru_RU.UTF-8'
lc_numeric = 'ru_RU.UTF-8'
lc_time = 'ru_RU.UTF-8'
#default_text_search_config = 'pg_catalog.russian'
#------------------------------------------------------------------------------
# LOCK MANAGEMENT
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# VERSION/PLATFORM COMPATIBILITY
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# CUSTOMIZED OPTIONS
#------------------------------------------------------------------------------

Сразу после установки postgresql и запуска его меняем пароль на роль postgres:

root# su - postgres
postgres> psql
postgres=# alter role postgres password 'some_password_you_like';
postgres=# \q
postgres> exit

Теперь можно цепляться к базе...


Читать далее

Черновик. Репликация средствами bucardo. №2

Итак, в прошлый раз история с репликацией ничем положительным не закончилась, так что начинаем по новому. Заглядывать в старые черновики не буду, начну писать новый.

Итак для начала на VMWare разворачиваю SLES10 SP2 (будет еще вариант со SLES9 SP3, SP4).
Делаю базовую настройку, как написано с соответствующей теме (Базовая настройка PostgreSQL 8.2.5 на linux).

Вытягиваю с http://bucardo.org последнюю версию bucardo. На тот момент это был Bucardo-3.0.9.tar.gz

Под postgres создаю язык:
CREATE LANGUAGE plpgsql;
Кроме того, в доке написано, что база, которую будет использовать bucardo должна имень установленный язык plperlu:

Bucardo requires that all databases involved in the replication be running version 8.1 or greater, and that they have the Pl/Pgsql language installed. The database that Bucardo itself uses must have the Pl/Perlu language installed.

Когда опрелелюсь, какая будет база, создам язык.
Кроме того есть требования для perl и его модулей:

Bucardo runs as a series of Perl daemons, and requires version 5.8.3 of Perl or better.The following modules are also required to run Bucardo:

  • DBI 1.51
  • DBD::Pg 1.49
  • *DBIx::Safe 1.2.4
  • Moose 0.18
  • IO::Handle 1.24
  • Sys::Hostname 1.11
  • Sys::Syslog
  • Mail::Sendmail 0.79
  • ExtUtils::MakeMaker 6.32

In order to run the test suite (highly recommended), the following modules are required:

  • Test::Simple 0.30
  • Test::More 0.61
  • Test::Harness 2.03
  • *Test::Dynamic 1.3.1

* These modules come bundled with Bucardo.

Итак модули со звездочкой нас не интересуют, так как по утверждению доки они в составе. Нужно найти остальные модули правильных версий. Искать будем на cpan.

DBI 1.51 нашел через google (в YaST есть только 1.50)

DBD::Pg 1.49 нашел через google

Moose 0.18 нашел через google

IO::Handle 1.24 оказался проблемным модулем. Судя по моим поискам в cpan он входит в состав модуля IO, но ни в одном IO в cpan нет IO::Handle необходимой версии. Поэтому я вытянул IO-1.2301 (там в составе IO::Handle 1.27)

Sys::Hostname 1.11 вообще не нашел. Судя по cpan он есть в составе perl-5.8.8, который установлен у меня.

Sys::Syslog не имеет никаких требований по версии. Нашел на cpan.

Mail::Sendmail 0.79 Нашел на cpan.

ExtUtils::MakeMaker 6.32 Нашел на cpan.

Test::Simple 0.30 тоже оказался проблемным. Такой древней версии на cpan нет. Вытянул Test-Simple-0.80, надеюсь подойдет.

Test::More 0.61 проблемный. находится в составе Test::Simple. То есть будем использовать тот вариант, что был выкачан в предыдущем пакете.

Test::Harness 2.03 проблемный. Такой старючей версии на cpan нет. Вытянул последнюю стабильную версию из 2-й ветки Test-Harness-2.62

Осталось только проставить эти модули.
Сначала ставим вот эти:

DBI-1.51
ExtUtils-MakeMaker-6.32
IO-1.2301
Sys-Syslog-0.27
Test-Harness-2.62
Test-Simple-0.80
Mail-Sendmail-0.79

Они для своей установки больше ничего не требуют. Ставим следующим образом. Логинимся под непривилегированным пользователем:

root# su - alexsf

Распаковываем их, поочереди заходим в папку каждого и под непривелигированным пользователем выполняем:

alexsf> perl Makefile.PL
alexsf> make
alexsf> make test

Смотрим внимательно на сообщения. Главное, чтоб не требовало дополнительным модулей и тесты прошли удачно. Потом под root в каждой папке выполняем:

root# make install

Смотрим на сообщения. Если ошибок нет, то все проставилось нормально.

Ставим модуль Moose-0.18:

alexsf> make Makefile.PL
Warning: prerequisite Class::MOP 0.37 not found.
Warning: prerequisite Sub::Exporter 0.972 not found.
Warning: prerequisite Sub::Name 0.02 not found.
Warning: prerequisite Test::Exception 0.21 not found.
Warning: prerequisite Test::LongString 0 not found.
Writing Makefile for Moose

То есть нужно теперь достать модули из этого списка.
Class::MOP 0.37 на cpan.
Sub::Exporter 0.972 не нашел. Есть Sub-Exporter-0.980, его и качаю.
Sub::Name 0.02 на cpan.
Test::Exception 0.21 нету. Есть Test-Exception-0.27, его и качаю.
Test::LongString версия не ясна. Вытянул то, что нашел - Test-LongString-0.11.

Ставим в таком порядке:
Sub-Name-0.02
Test-LongString-0.11

Test-Exception-0.27 требует модуль Sub::Uplevel 0.18 (на cpan есть). Ставим его, потом ставим Test-Exception-0.27.

Ставим Class::MOP 0.37.
Ставим Sub-Exporter-0.980. Ему нехватает:

Warning: prerequisite Data::OptList 0.1 not found.
Warning: prerequisite Params::Util 0.14 not found.
Warning: prerequisite Sub::Install 0.92 not found.

Ищем...
Data::OptList 0.1 не нашел, нашел Data-OptList-0.103 на cpan. Его и тянем.
Params::Util 0.14 не нашел, нашел Params-Util-0.33 на cpan. Его и тянем.
Sub::Install 0.92 не нашел, нашел Sub-Install-0.924 на cpan. Его и тянем.

Ставим в таком порядке:

Sub-Install-0.924
Params-Util-0.33
Data-OptList-0.103

Ну и наконец ставим Sub-Exporter-0.980. Уф, уже запарился с этими модулями... Так, для чего мы все это делали??? А, да, ставим Moose-0.18.

Теперь ставим DBD-Pg-1.49. Получилось.

Таперь беремся за сам Bucardo. Распаковываем куда-нибудь архивчик Bucardo-3.0.9.tar.gz под непривилегированным пользователем. Поочереди захидим в папки

DBIx-Safe-1.2.4
Test-Dynamic-1.3.2
Bucardo-3.0.9

и проставляем перловские модули, будь они неладны... Они там ругаться будут на ошибки - игнорируем и ставим все равно.

Теперь создаем базу данных для bucardo.

root# mkdir /u02
root# chown postgres:postgres /u02
root# su - postgres
postgres> mkdir /u02/pgdata/bucardo -p
postgres> psql
postgres=# CREATE USER bucardo SUPERUSER;
postgres=# ALTER ROLE bucardo password 'bucardo';
postgres=# CREATE TABLESPACE bucardo OWNER bucardo LOCATION '/u02/pgdata/bucardo';
postgres=# CREATE DATABASE bucardo WITH ENCODING='UTF8' OWNER=bucardo TABLESPACE=bucardo;
postgres=# CREATE LANGUAGE plperlu;

...и получаем

ERROR: нет доступа к файлу "$libdir/plperl": Нет такого файла или каталога

Ну а кто говорил, что будет просто... Роем...
Подозреваю, что нужен пакет postgresql-pl версии 8.2.5.
Итак, на http://software.opensuse.org/search нашел и скачал 2 пакета:

postgresql-pl-8.2.4-2.nosrc.rpm
postgresql-plperl-8.2.4-2.i586.rpm

Оба для OpenSUSE 10.3, но на SLES10 SP2 встали нормально, с установленным postgresql 8.2.5. Что я буду делать с SLES9 пока не знаю... Итак, нам же нужно язык проставить...


root# su - postgres
postgres> psql
postgres=# CREATE LANGUAGE plperlu;

Готово... Ур-р-р-р-а-а-а-а!!!! предвариловка закончена, начинаем трахаться по серьезному...
Создаем схемы для bucardo. Для этого переходим в каталог Bucardo-3.0.9, откуда ставили соответствующий модуль perl, и выполняем:

root# su postgres
postgres> psql -f bucardo.schema -h 10.77.1.9 -U bucardo bucardo

, где 10.77.1.9 - ip адрес сервера postgres. В результате получаем:

CREATE SCHEMA
CREATE SCHEMA
SET
SET
SET
CREATE TABLE
CREATE INDEX
CREATE INDEX
ALTER TABLE
psql:bucardo.schema:57: ERROR: язык "plpgsql" не существует
ПОДСКАЗКА: Use CREATE LANGUAGE to load the language into the database.

Так, вроде языки сделал уже все...
Не, нифига, языки оказались в базе postgres, а надо, чтоб были в базе bucardo. Поэтому:

postgres> psql -h 10.77.1.9 -U bucardo bucardo
bucardo=# CREATE LANGUAGE plpgsql;
bucardo=# CREATE LANGUAGE plperlu;
bucardo=# DROP SCHEMA bucardo CASCADE;
bucardo=# DROP SCHEMA freezer CASCADE;
bucardo=# \q
postgres> psql -f bucardo.schema -h 10.77.1.9 -U bucardo bucardo

и, о чудо, скрипт отработал без ошибок!!!

Делаем тест, как написано в документации:

alexsf> time make test TEST_VERBOSE=1
/usr/bin/perl t/bucardo.test.helper
PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(1, 'blib/lib', 'blib/arch')" t/*.t
t/01bc....Can't use string ("Test::Dynamic") as a HASH ref while "strict refs" in use at /usr/lib/perl5/site_perl/5.8.8/Test/Dynamic.pm line 30.
FAILED before any test output arrived
FAILED--1 test script could be run, alas--no output ever seen
make: *** [test_dynamic] Ошибка 255

real 0m0.250s
user 0m0.132s
sys 0m0.104s

Пробуем так:

alexsf> time make test TEST_VERBOSE=1 BUCARDO_TEST_NUKE_OKAY=1 BUCARDO_TESTBAIL=0 BUCARDO_KEEP_OLD_DEBUG=0

То же самое... Затык пока. Не знаю, забить на результаты теста и двигаться дальше, или разобраться???


Читать далее