Merhaba,
PostgreSQL 10 ile gelen yeniliklerden biri olan Logical Replication'dan bahsetmek isterim.
Logical Replication (LR), veri objelerini ve üzerlerindeki değişiklikleri, replikasyon kimliklerine göre (primary key gibi) replike eder. Yani aslında publisher veritabanından datanın snapshot’ının kopyalanmasıdır. Tüm değişiklikler tamamlandığında publisher üzerindeki değişiklikler subscriber’a real time olarak yollanır.
LR ile sadece normal tablolar replike edilebilir. Materialized view, view, partition’un root tablosu yada foreign tabloları replike edilemediği göz önünde tutulmalıdır. Ayrıca şema bazlı veri aktarımı yapılamamakta.
Farklı PostgreSQL versiyonları arasında LR yapılabilir. Birden fazla veritabanı üzerinden tek bir veritabanına LR yapılabilir. Farklı kullanıcı gruplarına replike olmuş datalar için yetki verilebilir. Veri objesi üzerinde yapılan her tekil değişiklik karşı tarafa aktarılır. Tek bir tablonun replikasyonu birden farklı cluster’lar üzerinde olabilir.
LR ile ilgili bir kaç kısıtlama bulunmakta.
- Veritabanı şemanları ve DDL komutları replike edilemez.
- Sequence replikasyonu yapılamaz.
- TRUNCATE komutları replike edilememektedir. TRUNCATE kullanmak yerine DELETE kullanılmalıdır. TRUNCATE konusunda önlem almak için kullanıcı yetkilerinde o tabloya ait truncate yetkisi geri alınabilir.
- Large objects replike edilemez ve LR failover için uygun değildir.
Publication
Publication fiziksel master replikasyon’u üzerinde tanımlanır. Publication’da ki node publisher olarak tanımlanır. Bir publication tabloların oluşturduğu bir gruptan yada bir tablodan oluşturulmuş değişikliklerin bütünüdür. Her publication sadece bir veritabanında mevcuttur.Publication’lar şemalardan farklıdır ve tabloya nasıl erişildiği onu etkilemez. İhtiyaç olursa her tablo farklı publication lara eklenebilir.
Publication’lar yapılacak değşikliklere limit getirebilir. INSERT, UPDATE, DELETE işlemlerinde birişi yada bir kaçını kombine edip kullanabilir. Default olarak tüm operasyon tipleri içinin replikasyon yapılır.
Published tabloları UPDATE ve DELETE işlemlerini yapabilmesi için “replica identity” ye ihtiyacı vardır. Bu genellikle primary key olur. Bu yoksa Unique Index replica identity olarak set edilebilir. Tabloda uygun bir key yoksa, replica identity FULL olarak set edilir. Bunun anlamı tüm satırlar key olarak belirlenir. Bu durum çok kullanışlı değildir ve bu yöntemi sadece eğer başka yolu yoksa son çare olarak kullanılmalıdır. Üzerinde replica identity tanımlı olmayan bir tablo bir UPDATE/DELETE işlemini yapan publication’a eklendiğinde, publisher tarafında hata alınacaktır. INSERT işlemi için replica identity’e ihtiyaç yoktur.
Her publication birden fazla subscriber’e sahip olabilir.
Subscription
Bir subscription’un tanımlandığı node subscriber olarak tanımlanır. Subscriber, diğer veritabanına bağlantıları ve subscribe’e gidecek olan publication’ları tanımlar.Subscriber birden fazla subscription’a sahip olabilir.
Örnek verelim;
Herşeyden önce master ve standby server üzerindeki postgresql.conf dosyasında wal_level=logical olarak değiştirilmelidir. Logical olarak değiştirilmesi mevcut streaming replication gibi diğer replikasyonlarınızın işleyişini bozmaz.
Replikasyonu sağlayacak kullanıcıya ihtiyacımız olacak. Bu kullanıcı mutlaka REPLICATION yetkisine sahip olmalıdır yada SUPERUSER olmalıdır. Erişim yetkisi için role pg_hba.conf üzerinde configure edilebilir ve bu kullanıcının LOGIN yetkisi mutlaka olmalıdır. Yetkiler sadece replication bağlantısının başladığı anda kontrol edilir. Her değişen row ile bu durum yeniden kontrol edilmez. Uygulanan her değişiklikte bu durum kontrol edilmez.
moon=# create role logical_rep with login replication password 'password';
Server üzerinde iki Postgresql 10 cluster’i kurdum. Master olana ait port 5410, standby olana ait portu 54102 olarak verdim.
Master üzerinde moon adında veritabanı oluşturdum. İçine iki adet tablo ekledim;
postgres=# create database moon;
CREATE DATABASE
moon=# create table students (id serial primary key, name text);
CREATE TABLE
moon=# create table teachers (id serial primary key, name text);
CREATE TABLE
Tablolar oluşturulduktan sonra LR için oluşturduğumuz logical_rep kullanıcısına tablolar için select yetkisi verilmelidir.
moon=# grant select on students to logical_rep ;
GRANT
moon=# grant select on teachers to logical_rep ;
GRANTStudents tablosuna veri ekleyelim;
moon=# insert into students (name) values ('usagi'), ('chibiusa'), ('mamoru'), ('makoto'), ('minako');
INSERT 0 5
Veriler master’dan geleceği için burada publication oluşturulur.
moon=# create publication moon_pub for table students ,teachers;
CREATE PUBLICATION
Burada istenirse tüm tablolar içinde de publication oluşturulabilir.
create publication moon_all for all tables;
Standby üzerinde moon_st adında bir veritabanı oluşturdum. Burada yapılması gereken stanby üzerinde subscription oluşturulması.
postgres=# create database moon_st;
CREATE DATABASE
Eğer publication için kullanılan tabloları oluşturmadan subscription oluşturmak istersem aşağıdaki hatayı alacağım.
moon_st=# create subscription my_sub connection 'host=localhost dbname=moon user=logical_rep password=password port=5410' publication moon_pub;
ERROR: relation "public.students" does not exist
Standby üzerinde de tablolarımı oluşturduktan sonra create subscription scriptimi çalıştırıyorum.
moon_st=# create subscription my_sub connection 'host=localhost dbname=moon user=logical_rep password=password port=5410' publication moon_pub;
NOTICE: created replication slot "my_sub" on publisher
CREATE SUBSCRIPTION
ADD TABLE veya DROP TABLE ifadeleri publication da da değişiklik yaratacağı için ALTER SUBSCRIPTION ... REFRESH PUBLICATION ifadesini tablolar üzerinde yapılacak bu değişiklik sonrası çalıştırılması unutulmamalıdır.
ALTER SUBSCRIPTION moon_pub REFRESH PUBLICATION;
Sevgiler,