czwartek, 12 czerwca 2014

Tworzenie replikacji primary-standby w PostgreSQLu

Przyszedł w końcu czas postawienie replikacji master-slave w PostgreSQLu. Ten post jest kontynuacją poprzedniego posta na temat wprowadzenia do replikacji, który możecie przeczytać tutaj. Przypominam, że ten system bazodanowy nie ma jeszcze replikacji master-master, ale jeśli by wam bardzo na tym zależało, to proponuje się zapoznać z projektem Bucardo, który daje taką możliwość.

Do postawienia PostgreSQLowej replikacji wykorzystam dwie maszyny:
  • Serwer A: zlokalizowany w Nowym Jorku, host: HOST-A
  • Serwer B: zlokalizowany w Amsterdamie, host: HOST-B

Zakładam, że serwer B będzie masterem, a serwer A slavem. Opisywałam już w poprzednich postach jak zainstalować serwer PostgreSQL dlatego zakładam, że spokojnie mogę pominąć ten krok. Jeśli jednak potrzebujecie pomocy w tych krokach, odsyłam do poprzednich postów gdzie opisuje instalację ze źródeł lub z paczki.

Konfigurujemy Master serwer (serwer B)

Na maszynie B działa już serwer z którego chcemy 'zrobić' mastera i dołączyć do niego tylko serwer standby. Dlatego zajmiemy się tylko konfiguracją. Zmieniamy główny plik konfiguracyjny PostgreSQLa postgresql.conf:

listen_addresses = '*'
wal_level = hot_standby 
archive_mode = on 
archive_command = 'cp %p /var/lib/pgsql/9.3/archive/%f'


#------------------------------------------------------------------------------
# REPLICATION
#------------------------------------------------------------------------------

# - Sending Server(s) -

# Set these on the master and on any standby that will send replication data.
max_wal_senders = 1
wal_keep_segments = 32
#wal_sender_timeout = 60s


Nie wszystkie z wymienionych opcji muszą być zmienione:
  • listen_addesses - z jakich adresów można się łączyć do serwera. Jeśli nie chcemy aby PostgreSQL słuchał na wszystkich adresach tak jak jest to na przykładzie ('*'), możemy wyszczególnić o jakie dokładnie adresy IP chodzi.
  • wal_level - wskazuje ile informacji ma być zapisywanych do plików WAL. minimal wskazuje na minimalna ilość informacji, która może tylko być pomocna przy procesie recovery po crashu serwera lub natychmiastowym zamknięciu. Nie pozwala jednak na rekonstrukcję danych. Do tego potrzebny jest poziom archive. Różnica między archive a hot_standby jest taka, że przy tym drugim zapisywane są dodatkowe informację potrzebne do zrekonstruowania statusu działającej transakcji z plików WAL. Poziom hot_standby jest wymagany aby działała Stream Replikacja.
  • archive_mode [NO/OFF] - Jeśli jest włączona, pliki WAL, które zostały w całości skompletowane, są wysyłane do archiwizacji przy użyciu polecenia zdefiniowanego przez archive_command. Ta opcja musi być włączona aby wal_level = archive lub hot_standby miał jakiś skutek.
  • archive_command - polecenie do archiwizacji plików WAL
  • max_wal_senders - definiuje maksymalną ilość połączeń z serwerów standby lub klientów programu do tworzenia base backupu. Domyśle ta liczba jest równa 0 co oznacza, że replikacja jest wyłączona.
  • wal_keep_segments - definiuje minimalną ilość starych plików logów segmentów trzymanych w katalogu pg_xlog
  • wal_sender_timeout - definiuje ile sekund ma upłynąć zanim zostanie zakończone połączenie replikacji, które jest nieaktywne. Ta opcja może być pomocna przy sprawdzaniu czy standby nie padł lub braku połączenia sieciowego. Przy wartości 0 ten mechanizm jest wyłączony.

Aby slave mógł pobierać dane z mastera, stworzymy użytkownika z prawami do logowania i replikacji lub musi to być superuser. (Nasz nowy user ma dostęp do strumieniowanych plików WAL czyli ma bardzo wysokie prawa dostępu ale nie ma możliwości dokonywania zmian na serwerze primary):

CREATE USER replication REPLICATION LOGIN CONNECTION LIMIT 1 ENCRYPTED PASSWORD 'replication';

Naszym celem jest stworzenie replikacji primary z jednym serwerem standby. Dlatego stworzony user ma ograniczenie do jednego połączenia na raz do serwera. Jeśli chcesz podłączyć więcej slavów do mastera, musisz zupdatować usera replication (zwiększając limit połączeń) lub stworzyć nowego usera.

Zmieniamy w pliku autoryzacji pg_hba.conf do serwera:

# Allow replication connections from localhost, by a user with the
# replication privilege.
host replication replication HOST-A/32 md5

Możemy uruchomić serwer.

Stawianie i konfiguracja serwera Standby (serwer A)

Ze względu na specyfikę działania replikacji w PostgreSQLu pliki danych binarnych muszą być takie same na serwerze Standby i Primary. Od wersji 9.1 dostępny jest i rekomendowany program pg_basebackup, który wykonuje binarną kopię plików klastra. Backup jest tworzony przy wykorzystaniu zwykłego połączenia do PostgreSQL i przy wykorzystaniu protokołu replikacji (Serwer primary musi mieć ustawiony max_wal_senders min = 1 aby połączenie doszło do skutku).

[root@niujork /home/postgres/psql9.3.4]$ mkdir data4
[root@niujork /home/postgres/psql9.3.4]$ chown -R postgres:postgres data4
[root@niujork /home/postgres/psql9.3.4]$ /usr/local/pgsql/bin/pg_basebackup -R -D /home/postgres/psql9.3.4/data4 --host=HOST-B -Ureplication -W
Password: 
NOTICE:  pg_stop_backup complete, all required WAL segments have been archived
[root@niujork /home/postgres/psql9.3.4]$ chown -R postgres:postgres data4

Program utworzył w katalogu data4 całą nową strukturę klastra i dodał nowy plik recovery.conf (opcja -R) z ustawieniami do uruchomienia Streaming Replication. Opcja -D wskazuje katalog docelowy gdzie klaser ma zostać 'zainstalowany'. Więcej na temat tego programu w dokumentacji tutaj.

[root@niujork /home/postgres/psql9.3.4/data4]$ cat recovery.conf 
standby_mode = 'on'
primary_conninfo = 'user=replication password=replication host=HOST-B port=5432 sslmode=disable sslcompression=1'

To zmienna standby_mode = 'on' świadczy o tym, że serwer PostgreSQL działa jako standby. Jeśli zmienna jest równa 'off' wszystkie inne już nie są brane pod uwagę. Zmienna primary_conninfo trzyma informację na temat połączenia do mastera. Przypominam, że user którego użyjemy musi być seperuser-em lub użytkownikiem z prawami do replikacji. Dane zostały automatycznie wypełnione przy skopiowaniu klastra przez pg_basebackup.

Nasz nowy serwer ma taki sam plik konfiguracyjny jak jego master, z którego została wykonana kopia klastra (możemy go zmienić i dostosować do własnych potrzeb). Aby było możliwe querowanie (tylko read-only) na serwerze standby, w pliku konfiguracyjnym postgresql.conf musimy mieć włączoną opcję:

# - Standby Servers -
# These settings are ignored on a master server.
hot_standby = on 

  • hot_standby - [ON/OFF] - Jeśli serwer jest włączony jako standby (standby_mode = 'on') i hot_standby = 'on' jest możliwe podłączenie się do serwera i wykonywanie poleceń read-only. 


Sprawdzenie działania replikacji

PostgreSQL udostępnia kilka prostych funkcji do sprawdzania statusu replikacji:
  • pg_is_in_recovery - funkcja do sprawdzania czy serwer działa w trybie recovery lub czy jest slavem
  • pg_last_xlog_receive_location - funkcja zwraca ostatnią lokalizację logu transakcji otrzymaną i zsynchronizaowaną na dysku przez stream replikację 
  • pg_last_xlog_replay_location - funkcja zwraca ostatnią lokalizację logu transakcji powtórzoną w trakcie recovery. Jeśli serwer wystartował normalnie bez recovery, funkcja zwróci NULL.
  • pg_last_xact_replay_timestamp - funkcja zwraca timestamp ostatniej transakcji powtarzanej w trakcie recovery
  • pg_xlogfile_name_offset - funkcja zwraca nazwę i offset pliku WAL pytanej lokalizacji transakcji
Od wersji 9.1 dostępny jest także widok do sprawdzania na serwerze primary stanu replikacji:

postgres=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid              | 31416
usesysid         | 16387
usename          | replication
application_name | walreceiver
client_addr      | HOST-A
client_hostname  | 
client_port      | 46924
backend_start    | 2014-06-11 05:53:51.971246-04
state            | streaming
sent_location    | 0/25008A08
write_location   | 0/25008A08
flush_location   | 0/25008A08
replay_location  | 0/25008A08
sync_priority    | 0
sync_state       | async

postgres=# SELECT * FROM pg_xlogfile_name_offset('0/25008A08');
        file_name         | file_offset 
--------------------------+-------------
 000000010000000000000025 |       35336
(1 row)



Tylko czy jesteśmy w stanie realnie sprawdzić jak bardzo nasz slave jest do tyłu w stosunku do mastera? Szukając dalej natknęłam się na ciekawy post (Monitoring Streaming Slave Lag Effectively) na temat monitoringu replikacji, a dokładniej sprawdzania opóźnienia serwera standby w stosunku do primary. Autor przedstawił w nim funkcję zwracającą w prosty sposób informację o slave podłączonym i jego opóźnieniu. Kod funkcji (musi być stworzona i uruchamiana przez superusera bo dane o które pytamy dotyczą nie tylko naszej sesji i użytkownika):

CREATE OR REPLACE FUNCTION streaming_slave_check() RETURNS TABLE (client_hostname text, client_addr inet, byte_lag float)
LANGUAGE SQL SECURITY DEFINER
AS $$
    SELECT
        client_hostname,
        client_addr,
        sent_offset - (replay_offset - (sent_xlog - replay_xlog) * 255 * 16 ^ 6 ) AS byte_lag
    FROM (
        SELECT
            client_hostname,
            client_addr,
            ('x' || lpad(split_part(sent_location,   '/', 1), 8, '0'))::bit(32)::bigint AS sent_xlog,
            ('x' || lpad(split_part(replay_location, '/', 1), 8, '0'))::bit(32)::bigint AS replay_xlog,
            ('x' || lpad(split_part(sent_location,   '/', 2), 8, '0'))::bit(32)::bigint AS sent_offset,
            ('x' || lpad(split_part(replay_location, '/', 2), 8, '0'))::bit(32)::bigint AS replay_offset
        FROM pg_stat_replication
    ) AS s; 
$$;

A to jego przykładowy wynik uruchomienia:

postgres=# select * from streaming_slave_check();
 client_hostname |   client_addr   | byte_lag 
-----------------+-----------------+----------
                 | HOST-A          |        0
(1 row)

Mam nadzieję, że ten krótki post będzie dobrym wstępem do dalszych prac nad replikacją w PostgreSQLu. Miłej zabawy.



środa, 11 czerwca 2014

PostgreSQL: wprowadzenie do replikacji


Pisałam już posta na temat instalacji PostgreSQLa ze źródeł oraz z paczki. Te informacje mogą się wam przydać aby postawić dwie maszyny, a następnie ustawić je tak aby działały w replikacji. Od wersji PostgreSQLa 9.0 mamy dostępną replikację primary-standby (nazywana także: master-slave). W Tym poście poopowiadam co nieco o teorii na ten temat, a w następnym przejdziemy do praktyki.

Podstawowym elementem przenoszenia danych między serwerami w PostgreSQLu są pliki WAL (Write-Ahead Logging), a ich wymiana nazywa jest Log Shipping. Dane w plikach WAL są zapisywane dopiero gdy transakcja została zacomitowane (czyli zakończyła się poprawnie i została zatwierdzona). Jest to proces asynchroniczny. Rozróżniamy File-Based Log Shipping, gdzie segmenty pliku WAL są przenoszone na raz oraz Record-Based Log Shipping, gdzie plik WAL jest strumieniowany.

Przyjrzymy się jednak historii powstawania replikacji w PostgreSQLu
  • PITR - Point-In-Time Recovery (PITR) - Dostępny od wersji 8.0. Nazywany jest także Incremental database backup, Online backup albo Archive backup. Logi transakcyjne są kopiowane i przechowywane, aż do momentu gdy są potrzebne. Jest głównie używany w diagnostyce i odzyskiwaniu danych po crashu głównego serwera.
  • Warm Standby - Dostępny od wersji 8.3. Logi transakcji są kopiowane do serwera standby i tak zatwierdzane jak tylko slave je otrzyma (log shipping). Serwer standby pracuje w trybie offline i nie może być używany do odczytu. Może jednak być uruchomiony do użycia w bardzo krótkim czasie.
  • Hot Standby - Dostępny od wersji 9.0. W porównaniu do Warm Standby, serwer standby jest dostępny do odczytu. Także wymaga file-based log shipping. Może być wykorzystywany także do pracy awaryjnej. Pliki WAL (o rozmiarach 16MB) mogą być przenoszone pomiędzy wiele serwerów poprzez sieć. Nie wymaga to podłączenia do bazy danych ale miejsca na dysku.
  • Streaming Replication - Dostępny od wersji 9.1. Zamiast kopiować logi plików, dla każdego slava otwierane jest połączenie do mastera poprzez połączenia TCP/IP (może spowodować to wzrost obciążenia na bazie master). Zostało to stworzone poprzez utworzenie na masterze i slave dwóch procesów: walsender i walreceiver, które przenoszą zmodyfikowane dane stron między portami sieci. Dzięki temu zmiany z głównej bazy są widoczne prawie natychmiast na serwerze standby. W normalnym działaniu Stream Replication nie wymaga log shipping, ale może być pomocna przy starcie.
Schemat działania Streaming Replikacji:



Hot Standby i Streaming Replication są nazywane także replikacją binarną, mimo iż są różne. Głównymi cechami replikacji binarnej w PostgreSQLu są:
  • replikacja całego klastra - nie ma możliwości wyróżnienia pojedynczej schematu/bazy danych/tabeli
  • możliwe jest uruchomienie load-balacu pomiędzy zapytaniami czytania/pisania między masterem a slavami
  • replikowane są także wszystkie zapytania DDL (Data Definition Langue) - zmiany w tabelach i indexach, tworzenie indexów i baz danych
  • nie jest możliwe replikacja pomiędzy różnymi wersjami PostgreSQL-a lub między różnymi platformami
  • nie ma możliwości utworzenia replikacji multi-master (tego typu architektura jest podobno (bo jeszcze nie testowałam) możliwa przy pomicy Bucardo)

Mam nadzieję, że rozumiecie główną idee i działanie replikacji tak abyśmy przeszli do praktyki.


poniedziałek, 9 czerwca 2014

Instalacja PostgreSQLa z RPMa

Instalowaliśmy już PostgreSQLa ze źródeł. Ale co jeśli jednak chcemy zainstalować go przy pomocy paczki RPM. Jest to pewnie dziecinnie proste bo w końcu paczki zostały zbudowane po to aby zrobić właściwie wszystko za nas. Sprawdźmy to.

Mój system operacyjny to Centos 64Bitowy i chce na nim zainstalować najnowszą wersję serwera 9.3. Lista paczek RPM jest dostępna tutaj. Ale właściwie to dlaczego nie zainstaluję serwera bezpośrednio z repozytorium yum-a w ten sposób?! :

yum install postgresql-server

Dla mojego systemu operacyjnego w ten sposób dostępna jest wersja 8.4, a nie ta której ja potrzebuję. Dostępną wersje w repozytorium RPM możecie sprawdzić sami:

[root@amsterdam ~]$ yum info postgresql-server
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.supportex.net
 * extras: mirror.widexs.nl
 * updates: mirror.widexs.nl
Available Packages
Name        : postgresql-server
Arch        : x86_64
Version     : 8.4.20
Release     : 1.el6_5
Size        : 3.4 M
Repo        : updates
Summary     : The programs needed to create and run a PostgreSQL server
URL         : http://www.postgresql.org/
License     : PostgreSQL
Description : The postgresql-server package includes the programs needed to create
            : and run a PostgreSQL server, which will in turn allow you to create
            : and maintain PostgreSQL databases.  PostgreSQL is an advanced
            : Object-Relational database management system (DBMS) that supports
            : almost all SQL constructs (including transactions, subselects and
            : user-defined types and functions). You should install
            : postgresql-server if you want to create and maintain your own
            : PostgreSQL databases and/or your own PostgreSQL server. You also need
            : to install the postgresql package.

Ale przejdźmy do naszego głównego tematu. Proces instalacji i uruchomienia serwera składa się z kilku kroków:
  1. Instalujemy repozytorium RPM

    yum install http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-centos93-9.3-1.noarch.rpm
    

    Skoro w głównym repozytorium jest dostępna tylko stara wersji serwera, musimy zainstalować nowe repozytorium. Lista dostępnych repozytoriów jest http://yum.postgresql.org/repopackages.php.

  2. Instalujemy i updatujemy paczkę:

    yum install postgresql93-server postgresql93-contrib

    Wybierzcie dobrze nazwę paczki aby zainstalować tą z naszą pożądaną wersją serwera. Jeśli nie jesteście pewni co do jej nazwy, znajdzie ją przy pomocy polecenia: yum list | grep pgdg93

  3. Inicjalizujemy bazę danych

    service postgresql-9.3 initdb
    

    Gdy już serwer został zainstalowany, musimy zainicjować klaser bazy danych (czyli katalog, w którym będą trzymane pliki). To tak jak byśmy wykonali polecenie:

    /usr/pgsql-9.3/bin/initdb -D /var/lib/pgsql/9.3/data
    

  4. Aktywujemy usługę

    chkconfig postgresql-9.3 on
    

    Aby sprawdzić, jakie poziomy uruchomienia są włączone, wykonaj komendę (trochę więcej o tym poleceniu tutaj):

    [root@amsterdam ~]$ chkconfig --list postgresql-9.3
    postgresql-9.3  0:wyłączone 1:wyłączone 2:włączone 3:włączone 4:włączone 5:włączone 6:wyłączone
    

  5. Uruchamiamy serwer

    service postgresql-9.3 start

    Aby sprawdzić czy serwer działa, możemy wykonać polecenie:

    [root@amsterdam ~]$ service postgresql-9.3 status
    postgresql-9.3 (pid  1321) is running...
    

  6. Tworzymy użytkownika i bazę danych

    sudo su postgres
    createdb test
    createuser --createdb --login --pwprompt --createrole root
    

Katalog główny z danymi został zainstalowany na ścieżce: /var/lib/pgsql/9.3/data/. Oczywiście możemy tam znaleźć pliki konfiguracyjne postgresql.conf i pg_hba.conf.

wtorek, 3 czerwca 2014

PGLoader v3

W ostatnim poście pisałam o narzędziu pgloader służący do importu danych do PostgreSQLa. Nowa wersja została przepisana w całości na język Common Lisp. Do zapisu i odczytu danych używane są dwa oddzielne wątki, które współdzielą pracę. To co się nie zmieniło to to, że do komunikacji PostgreSQL nadal używany jest protokołu COPY. Tutaj odsyłam do post na temat nowej wersji tego narzędzia.

Przykład instrukcji załadowania pliku CSV:

LOAD CSV  
   FROM '/root/pgloader_data.csv'
   INTO postgresql://root:password@188.226.251.1/pgloader?pgloader_test(c2,c3)
 
   WITH truncate,  
        skip header = 0,
        fields optionally enclosed by '"',  
        fields escaped by double-quote,  
        fields terminated by ','  
 
   SET client_encoding to 'utf8', 
 work_mem to '12MB', 
 standard_conforming_strings to 'on'
 
BEFORE LOAD DO  
    $$ drop table if exists pgloader_test; $$,  
    $$ create table pgloader_test (
        c1 serial,
        c2 varchar(20),  
        c3 integer
       );  
    $$; 


Ładujemy dane:

[root@niujork ~]$ pgloader  pgloader.load 
2014-06-03T14:54:53.046000Z LOG Starting pgloader, log system is ready.
2014-06-03T14:54:53.076000Z LOG Main logs in '/tmp/pgloader/pgloader.log'
2014-06-03T14:54:53.082000Z LOG Data errors in '/tmp/pgloader/'
2014-06-03T14:54:53.083000Z LOG Parsing commands from file #P"/root/pgloader.load"
2014-06-03T14:54:59.686000Z ERROR Database error 22P02: invalid input syntax for integer: "sldkfhg"
CONTEXT: COPY pgloader_test, line 2, column c3: "sldkfhg"


                    table name       read   imported     errors            time

                   before load          2          2          0          2.701s
------------------------------  ---------  ---------  ---------  --------------
                 pgloader_test     219175     219174          1         18.568s
------------------------------  ---------  ---------  ---------  --------------
------------------------------  ---------  ---------  ---------  --------------
             Total import time     219175     219174          1         21.269s


Ładujemy dane gdzie pierwsza komuna jest varchar, a druga integer. Dla niepoprawnych danych, narzędzie wyświetla błędy ale reszta danych zostanie zaimportowana poprawnie.

Innym dodatkowym atutem jest możliwość ładowania danych z innych systemów bazodanowych: MySQL, SQLite czy dBase, a także odczytywanie danych z plików zarchiwizowanych czy danych o stałej szerokości. Jeśli musicie zaimportować dane do PostgreSQL, to polecam to narzędzie. Może się wam bardzo przydać.

Zainteresowanych odsyłam do dokumentacji tutaj.