PostgreSQL Majör Upgrade Yöntemleri

PostgreSQL veri tabanlarınızda majör versiyon yükseltmesi yapmanız için 3 farklı yöntem mevcut. Bunlar :

  • pg_dumpall ile tüm verinin hedef versiyonda yaratılmış bir veritabanı cluster’ına taşınması
  • pg_upgrade ile system tablolarının yenilenmesi ve kullanıcı verilerinin olduğu gibi kullanılması
  • Logical replication ile tüm verinin standby ortamda yeni versiyona taşınması ve switch-over ile rol değişimi yapılması.

Bu yöntemlerin avantaj/dezavantajları anlamında hızlıca üzerlerinden geçelim. pg_dumpall ile upgrade yapmak tüm veriyi kopyalamak anlamına geldiği için veri tabanı boyutu büyüdükçe uygulanabilirliği azalır. Boyut büyüdükçe kesinti süresi ve veri aktarımında hata ihtimali artacaktır. Ayrıca upgrade işlemi için ihtiyacımız olacak disk alanı da bir sorun haline gelebilir. Avantaj olarak ise eski versiyondaki cluster verilerinin üzerine yazılmamasından dolayı işlemin tehlikesiz olmasından, ayrıca veri tabanlarındaki tüm objelerin yeniden yaratılması ile fragmantasyon ve “index bloat” gibi sorunların giderilmesinden bahsedebiliriz. Ayrıca data export ve import işlemlerini aşağıdaki örnekteki gibi tek bir komutla yaparak upgrade işlemimizi hızlandırma opsiyonumuz da bulunmaktadır.

$ pg_dumpall -p 5432 | psql -d postgres -p 5433

Bu yöntem ile upgrade adımlarını PostgreSQL dökümantasyonundan inceleyebilirsiniz:

pg_upgrade ise büyük boyutlarda işimizi kolaylaştıracak bir yöntemdir. pg_upgrade’in sunduğu “–link” seçeneği ile verinin taşınmasına gerek kalmadan mevcut data file’lar, üzerinde “hard link” oluşturarak kullanılabilir. (Bu arada, varsayılan ayarlarda çalıştırılırsa pg_upgrade veri tabanı dosyalarını eski versiyondaki data dizininden yeni versiyondaki data dizinine kopyalar) Link yönteminde eski versiyon cluster, upgrade işleminden sonra yeniden sağlıklı bir şekilde açılamayacaktır, bunun için upgrade öncesinde veri tabanlarının yedeğinin alınması önemlidir. Bir diğer önemli nokta link modunda upgrade yapabilmemiz için eski ve yeni cluster’ın data dizinlerinin aynı filesystem üzerinde olması gerektiğidir. pg_upgrade’in “–check” opsiyonu ile upgrade işlemini yapmadan önce kontrolleri gerçekleştirmek de mümkündür. Yine PostgreSQL resmi dökümantasyonunda daha detaylı bilgi bulabilirsiniz.

Üçüncü yöntem ise “logical replication” konfigüresyonunun farklı versiyonlarda (primary/standby) çalışabilme avantajını kullanarak, yine büyük boyuttaki veri tabanlarının upgrade süresini minimalde tutmak için tercih edebileceğimiz bir seçenektir. Standby veri tabanımızı ister primary ile aynı sunucuda ister farklı bir sunucuda ve hedef PostgreSQL versiyonunda kurup replikasyon konfigürasyonunu tamamladıktan sonra, veri tabanları senkron iken switch-over işlemini yaparak kısa sürede upgrade işlemini tamamlamış olabiliriz. Detaylar için

PostgreSQL major upgrade kapsamında bu üç yöntemi inceledikten sonra, Ubuntu/Debian ortamlarda işimizi kolaylaştıran “pg_upgradecluster” dan da bahsedeceğiz. “postgresql-common” paketi ile birlikte gelen bu program PostrgeSQL cluster’ın yeni versiyona upgrade işlemini tek komut ile yaparken, eski versiyonun konfigürasyon dosyaları da yeni versiyon cluster’a uygun şekilde ayarlanarak kopyalanır. “pg_upgradecluster” kullanırken, upgrade yöntemi için pg_dump’ı ya da pg_upgrade’i seçebiliyoruz.

-m, –method=dump|upgrade|link|clone

“dump” seçeneği pg_dump ve pg_restore kullanırken, “upgrade” seçeneği pg_upgrade kullanır, varsayılan değer “dump”tır.
“link” seçeneği “upgrade –link” için kısayoldur ve pg_upgrade ‘i link opsiyonu ile birlikte kullanır.
“clone” ise yine “upgrade –clone” için kısayoldur ve pg_upgrade ‘i clone opsiyonu ile birlikte kullanır.

Daha önce bahsetmediğimiz “pg_upgrade –clone” seçeneği sadece belirli filesystem’lerin desteklediği bir opsiyondur ve upgade sırasında eski cluster’daki dosyaların bir klonunu yeni cluster’da hard link yöntemindeki gibi hızlı bir şekilde oluştururken, hard link’ten farklı olarak eski dosyaların orjinal bloklarını saklayarak eski cluster’ı açılabilir kılar. “reflink” olarak da bilinen bu yöntem aslında iki farklı dosyanın ortak veri bloklarını kullanmasını sağlayan bir filesystem özelliğidir.

pg_upgradecluster ‘ın man sayfasında daha fazla bilgi bulabilir ve komut opsiyonlarını inceleyebilirsiniz.

Şimdi PostgreSQL 16 versiyonundaki cluster’ımızı 17 versiyonuna pg_upgradecluster ile upgrade etme adımlarının üzerinden geçelim. Örneğimizde iki tane 16 versiyonunda cluster çalışmakta ve bunlardan birini 17 versiyonuna upgrade edeceğiz.

# pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
16  main    5432 online postgres /var/lib/postgresql/16/main /var/log/postgresql/postgresql-16-main.log
16  test    5433 online postgres /var/lib/postgresql/16/test /var/log/postgresql/postgresql-16-test.log

Öncelikle sunucumuza yeni versiyon PostgreSQL kurulumunu yapıyoruz.

# sudo apt-get upgrade
# wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
# sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" >> /etc/apt/sources.list.d/pgdg.list'
# sudo apt-get  install postgresql-17 postgresql-client-17

Yeni versiyonun kurulumu ile birlikte “main” isminde yeni bir cluster da otomatik olarak başlatıldı. Bu cluster’ı kullanmayacağımız için siliyoruz.

# pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
16  main    5432 online postgres /var/lib/postgresql/16/main /var/log/postgresql/postgresql-16-main.log
16  test    5433 online postgres /var/lib/postgresql/16/test /var/log/postgresql/postgresql-16-test.log
17  main    5434 online postgres /var/lib/postgresql/17/main /var/log/postgresql/postgresql-17-main.log

# pg_dropcluster --stop 17 main

# pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
16  main    5432 online postgres /var/lib/postgresql/16/main /var/log/postgresql/postgresql-16-main.log
16  test    5433 online postgres /var/lib/postgresql/16/test /var/log/postgresql/postgresql-16-test.log

Şimdi pg_upgradecluster komutunu varsayılan ayarları ile kullanarak “test” ismindeki cluster’ı 17 versiyonuna güncelliyoruz. Bu işlem 17 versiyonunda “test” isimli bir cluster yaratacak ve pg_dump kullanarak verileri yeni cluster’a taşıyacak. Aynı zamanda konfigürasyon dosyalarını taşıyacak ve 16 versiyonundaki eski cluster’ın port numarasını da değiştirecektir.

# pg_upgradecluster 16 test

	Stopping old cluster...
	Restarting old cluster with restricted connections...
	Notice: extra pg_ctl/postgres options given, bypassing systemctl for start operation
	Creating new PostgreSQL cluster 17/test ...
	/usr/lib/postgresql/17/bin/initdb -D /var/lib/postgresql/17/test --auth-local peer --auth-host scram-sha-256 --no-instructions --encoding UTF8 --lc-collate en_US.UTF-8 --lc-ctype en_US.UTF-8 --locale-provider libc
	The files belonging to this database system will be owned by user "postgres".
	This user must also own the server process.

	The database cluster will be initialized with locale "en_US.UTF-8".
	The default text search configuration will be set to "english".

	Data page checksums are disabled.

	fixing permissions on existing directory /var/lib/postgresql/17/test ... ok
	creating subdirectories ... ok
	selecting dynamic shared memory implementation ... posix
	selecting default "max_connections" ... 100
	selecting default "shared_buffers" ... 128MB
	selecting default time zone ... Etc/UTC
	creating configuration files ... ok
	running bootstrap script ... ok
	performing post-bootstrap initialization ... ok
	syncing data to disk ... ok

	Copying old configuration files...
	Copying old start.conf...
	Copying old pg_ctl.conf...
	Starting new cluster...
	Notice: extra pg_ctl/postgres options given, bypassing systemctl for start operation
	Running init phase upgrade hook scripts ...

	Roles, databases, schemas, ACLs...
	 set_config
	------------

	(1 row)

	 set_config
	------------

	(1 row)

	Fixing hardcoded library paths for stored procedures...
	Upgrading database postgres...
	Fixing hardcoded library paths for stored procedures...
	Upgrading database template1...
	Stopping target cluster...
	Stopping old cluster...
	Disabling automatic startup of old cluster...
	Starting upgraded cluster on port 5433...
	Running finish phase upgrade hook scripts ...
	vacuumdb: processing database "postgres": Generating minimal optimizer statistics (1 target)
	vacuumdb: processing database "template1": Generating minimal optimizer statistics (1 target)
	vacuumdb: processing database "postgres": Generating medium optimizer statistics (10 targets)
	vacuumdb: processing database "template1": Generating medium optimizer statistics (10 targets)
	vacuumdb: processing database "postgres": Generating default (full) optimizer statistics
	vacuumdb: processing database "template1": Generating default (full) optimizer statistics

	Success. Please check that the upgraded cluster works. If it does,
	you can remove the old cluster with
		pg_dropcluster 16 test

	Ver Cluster Port Status Owner    Data directory              Log file
	16  test    5434 down   postgres /var/lib/postgresql/16/test /var/log/postgresql/postgresql-16-test.log
	Ver Cluster Port Status Owner    Data directory              Log file
	17  test    5433 online postgres /var/lib/postgresql/17/test /var/log/postgresql/postgresql-17-test.log


# pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
16  main    5432 online postgres /var/lib/postgresql/16/main /var/log/postgresql/postgresql-16-main.log
16  test    5434 down   postgres /var/lib/postgresql/16/test /var/log/postgresql/postgresql-16-test.log
17  test    5433 online postgres /var/lib/postgresql/17/test /var/log/postgresql/postgresql-17-test.log

Şimdi ise pg_upgradecluster çalıştırırken “pg_upgrade –link” yöntemini kullanalım. Güncellediğimiz cluster’ı silerek, eski test cluster’ımızı yeniden açalım ve sonrasında pg_upgradecluster komutunu “link” yöntemi ile ve “parallel”, “rename” opsiyonlarını da deneyerek çalıştıralım.

# pg_dropcluster 17 test --stop
# pg_ctlcluster start 16 test
# pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
16  main    5432 online postgres /var/lib/postgresql/16/main /var/log/postgresql/postgresql-16-main.log
16  test    5434 online postgres /var/lib/postgresql/16/test /var/log/postgresql/postgresql-16-test.log


# pg_upgradecluster 16 test --method link --jobs 2 --rename test17

	Stopping old cluster...
	Creating new PostgreSQL cluster 17/test17 ...
	/usr/lib/postgresql/17/bin/initdb -D /var/lib/postgresql/17/test17 --auth-local peer --auth-host scram-sha-256 --no-instructions --encoding UTF8 --lc-collate en_US.UTF-8 --lc-ctype en_US.UTF-8 --locale-provider libc
	The files belonging to this database system will be owned by user "postgres".
	This user must also own the server process.

	The database cluster will be initialized with locale "en_US.UTF-8".
	The default text search configuration will be set to "english".

	Data page checksums are disabled.

	fixing permissions on existing directory /var/lib/postgresql/17/test17 ... ok
	creating subdirectories ... ok
	selecting dynamic shared memory implementation ... posix
	selecting default "max_connections" ... 100
	selecting default "shared_buffers" ... 128MB
	selecting default time zone ... Etc/UTC
	creating configuration files ... ok
	running bootstrap script ... ok
	performing post-bootstrap initialization ... ok
	syncing data to disk ... ok

	Copying old configuration files...
	Copying old start.conf...
	Copying old pg_ctl.conf...
	Running init phase upgrade hook scripts ...

	/usr/lib/postgresql/17/bin/pg_upgrade -b /usr/lib/postgresql/16/bin -B /usr/lib/postgresql/17/bin -p 5434 -P 5433 -d /etc/postgresql/16/test -D /etc/postgresql/17/test17 --link -j 2
	Finding the real data directory for the source cluster        ok
	Finding the real data directory for the target cluster        ok
	Performing Consistency Checks
	-----------------------------
	Checking cluster versions                                     ok
	Checking database user is the install user                    ok
	Checking database connection settings                         ok
	Checking for prepared transactions                            ok
	Checking for contrib/isn with bigint-passing mismatch         ok
	Checking data type usage                                      ok
	Creating dump of global objects                               ok
	Creating dump of database schemas
																  ok
	Checking for presence of required libraries                   ok
	Checking database user is the install user                    ok
	Checking for prepared transactions                            ok
	Checking for new cluster tablespace directories               ok

	If pg_upgrade fails after this point, you must re-initdb the
	new cluster before continuing.

	Performing Upgrade
	------------------
	Setting locale and encoding for new cluster                   ok
	Analyzing all rows in the new cluster                         ok
	Freezing all rows in the new cluster                          ok
	Deleting files from new pg_xact                               ok
	Copying old pg_xact to new server                             ok
	Setting oldest XID for new cluster                            ok
	Setting next transaction ID and epoch for new cluster         ok
	Deleting files from new pg_multixact/offsets                  ok
	Copying old pg_multixact/offsets to new server                ok
	Deleting files from new pg_multixact/members                  ok
	Copying old pg_multixact/members to new server                ok
	Setting next multixact ID and offset for new cluster          ok
	Resetting WAL archives                                        ok
	Setting frozenxid and minmxid counters in new cluster         ok
	Restoring global objects in the new cluster                   ok
	Restoring database schemas in the new cluster
																  ok
	Adding ".old" suffix to old global/pg_control                 ok

	If you want to start the old cluster, you will need to remove
	the ".old" suffix from /var/lib/postgresql/16/test/global/pg_control.old.
	Because "link" mode was used, the old cluster cannot be safely
	started once the new cluster has been started.
	Linking user relation files
																  ok
	Setting next OID for new cluster                              ok
	Sync data directory to disk                                   ok
	Creating script to delete old cluster                         ok
	Checking for extension updates                                ok

	Upgrade Complete
	----------------
	Optimizer statistics are not transferred by pg_upgrade.
	Once you start the new server, consider running:
		/usr/lib/postgresql/17/bin/vacuumdb --all --analyze-in-stages
	Running this script will delete the old cluster's data files:
		./delete_old_cluster.sh
	pg_upgradecluster: pg_upgrade output scripts are in /var/log/postgresql/pg_upgradecluster-16-17-test17.WyLf
	Disabling automatic startup of old cluster...
	Starting upgraded cluster on port 5434...
	Running finish phase upgrade hook scripts ...
	vacuumdb: processing database "postgres": Generating minimal optimizer statistics (1 target)
	vacuumdb: processing database "template1": Generating minimal optimizer statistics (1 target)
	vacuumdb: processing database "postgres": Generating medium optimizer statistics (10 targets)
	vacuumdb: processing database "template1": Generating medium optimizer statistics (10 targets)
	vacuumdb: processing database "postgres": Generating default (full) optimizer statistics
	vacuumdb: processing database "template1": Generating default (full) optimizer statistics

	Success. Please check that the upgraded cluster works. If it does,
	you can remove the old cluster with
		pg_dropcluster 16 test

	Ver Cluster Port Status Owner    Data directory              Log file
	16  test    5433 down   postgres /var/lib/postgresql/16/test /var/log/postgresql/postgresql-16-test.log
	Ver Cluster Port Status Owner    Data directory                Log file
	17  test17  5434 online postgres /var/lib/postgresql/17/test17 /var/log/postgresql/postgresql-17-test17.log



# pg_lsclusters
Ver Cluster Port Status Owner    Data directory                Log file
16  main    5432 online postgres /var/lib/postgresql/16/main   /var/log/postgresql/postgresql-16-main.log
16  test    5433 down   postgres /var/lib/postgresql/16/test   /var/log/postgresql/postgresql-16-test.log
17  test17  5434 online postgres /var/lib/postgresql/17/test17 /var/log/postgresql/postgresql-17-test17.log

Upgrade işlemi ile birlikte pg_upgradecluster’ın gerçekleştirdiği pre ve post işlemleri de komut çıktısında görebilirsiniz. Çıktıdaki şu uyarı link modu kullanıldığını ve yeni versiyon cluster açıldıktan sonra eski cluster’ın sağlıklı bir şekilde açılamayacağını belirtiyor: Because “link” mode was used, the old cluster cannot be safely started once the new cluster has been started.

Yöntemden bağımsız olarak upgrade işlemlerindeki en önemli iki nokta, doğru hazırlık ve geri dönüş planı oluşturmadır. Doğru hazırlık aşamasında veri tabanında çalışan tüm uygulamaların veri tabanının hedef versiyonunda test edilmeleri, ayrıca upgrade adımlarının da test ve dökümante edilmesi çok önemlidir. Geri dönüş planı ise upgade işlemi sırasında ya da sonrasında yaşanabilecek ciddi sorunlara karşı bir hazırlıktır. Veri tabanının yeni versiyona sağlıklı geçememesi ya da yeni versiyonda uygulama fonksiyonlarının doğru çalışmaması ile birlikte kısa süre içinde düzeltme şansının da olmaması durumlarında, eski versiyona veri kaybı olmadan geçebilmek gereklidir. Bunun için geri dönüş planımızı upgrade öncesinde oluşturmalı ve test etmeliyiz.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir