Data publikacji: Sep 23, 2012 4:56:28 PM
1. Dodać do /etc/apt/sources.list
deb http://pgapt.debian.net/ squeeze-pgdg main
deb-src http://pgapt.debian.net/ squeeze-pgdg main
Jeżeli korzystamy z innej (nowszej) wersji, najpierw określamy co mamy:
# lsb_release -c
Codename: wheezy
A później zastępujemy ciąg "squeeze" przez naszą dystrybucję (tutaj "wheezy").
Jeżeli interesuje nas wersja testowa bazy, zastępujemy ciąg "pgdg" przez "pgdg-testing" i po "main" dopisujemy wersję bazy danych, którą chcemy testować, np. "9.5"
2. Dodać klucz, zaktualizować listę pakietów
# wget http://pgapt.debian.net/ACCC4CF8.asc -O - | apt-key add -
# apt-get update
3. Zainstalować potrzebne wersje postgresql:
# apt-get -t squeeze-pgdg postgresql-9.2 ...
1. Dodać nowe repozytorium
# add-apt-repository ppa:pitti/postgresql
2. Zainstalować potrzebne wersje postgresql:
# apt-get postgresql-9.2 ...
Należy nałożyć łatkę postgresql-common-init.d-functions.patch z załącznika:
# cat postgresql-common-init.d-functions.patch | patch -p0 -l
Po jej nałożeniu, jeżeli chcemy wykonać operację start na clustrze 9.2/main wykonujemy:
/etc/init.d/postgresql 9.2/main start
Nie podanie nazwy clustra wykonuje operację na wszystkich clustrach w określonej wersji.
1. Upewniamy się, że mamy zainstalowany pakiet postgresql-server-dev-X.X:
# apt-get -t squeeze-pgdg install postgresql-server-dev-8.4 postgresql-server-dev-9.0 postgresql-server-dev-9.1 postgresql-server-dev-9.2
2. Na starcie sytuacja wygląda tak:
# pg_lsclusters
Version Cluster Port Status Owner Data directory Log file
8.4 main 5432 down postgres /var/lib/postgresql/8.4/main /var/log/postgresql/postgresql-8.4-main.log
3. Tworzymy nowy klaster czyli 9.0 / main.
# pg_createcluster 9.0 main
4. Sytuacja wygląda teraz tak:
# pg_lsclusters
Version Cluster Port Status Owner Data directory Log file
8.4 main 5432 down postgres /var/lib/postgresql/8.4/main /var/log/postgresql/postgresql-8.4-main.log
9.0 main 5433 down postgres /var/lib/postgresql/9.0/main /var/log/postgresql/postgresql-9.0-main.log
5. Wykonujemy czynności przygotowawcze:
# cd /tmp
# sudo -H -u postgres /usr/lib/postgresql/9.0/bin/pg_upgrade \
--old-datadir /var/lib/postgresql/8.4/main \
--new-datadir /var/lib/postgresql/9.0/main \
--old-bindir /usr/lib/postgresql/8.4/bin \
--new-bindir /usr/lib/postgresql/9.0/bin \
-o ' -c config_file=/etc/postgresql/8.4/main/postgresql.conf' -O ' \
-c config_file=/etc/postgresql/9.0/main/postgresql.conf' \
--check
Performing Consistency Checks
-----------------------------
Checking old data directory (/var/lib/postgresql/8.4/main) ok
Checking old bin directory (/usr/lib/postgresql/8.4/bin) ok
Checking new data directory (/var/lib/postgresql/9.0/main) ok
Checking new bin directory (/usr/lib/postgresql/9.0/bin) ok
Checking for reg* system oid user data types ok
Checking for /contrib/isn with bigint-passing mismatch ok
Checking for large objects ok
Checking for presence of required libraries ok
*Clusters are compatible*
6. Wykonujemy upgrade:
# cd /tmp
# sudo -H -u postgres /usr/lib/postgresql/9.0/bin/pg_upgrade \
--old-datadir /var/lib/postgresql/8.4/main \
--new-datadir /var/lib/postgresql/9.0/main \
--old-bindir /usr/lib/postgresql/8.4/bin \
--new-bindir /usr/lib/postgresql/9.0/bin \
-o ' -c config_file=/etc/postgresql/8.4/main/postgresql.conf' -O ' \
-c config_file=/etc/postgresql/9.0/main/postgresql.conf'
Performing Consistency Checks
-----------------------------
Checking old data directory (/var/lib/postgresql/8.4/main) ok
Checking old bin directory (/usr/lib/postgresql/8.4/bin) ok
Checking new data directory (/var/lib/postgresql/9.0/main) ok
Checking new bin directory (/usr/lib/postgresql/9.0/bin) ok
Checking for reg* system oid user data types ok
Checking for /contrib/isn with bigint-passing mismatch ok
Checking for large objects ok
Creating catalog dump ok
Checking for presence of required libraries ok
| If pg_upgrade fails after this point, you must
| re-initdb the new cluster before continuing.
| You will also need to remove the ".old" suffix
| from /var/lib/postgresql/8.4/main/global/pg_control.old.
Performing Migration
--------------------
Adding ".old" suffix to old global/pg_control ok
Analyzing all rows in the new cluster ok
Freezing all rows on the new cluster ok
Deleting new commit clogs ok
Copying old commit clogs to new server ok
Setting next transaction id for new cluster ok
Resetting WAL archives ok
Setting frozenxid counters in new cluster ok
Creating databases in the new cluster ok
Adding support functions to new cluster ok
Restoring database schema to new cluster ok
Removing support functions from new cluster ok
Restoring user relation files
ok
Setting next oid for new cluster ok
Creating script to delete old cluster ok
Checking for large objects ok
Upgrade complete
----------------
| Optimizer statistics is not transferred by pg_upgrade
| so consider running:
| vacuumdb --all --analyze-only
| on the newly-upgraded cluster.
| Running this script will delete the old cluster's data files:
| /var/lib/postgresql/9.0/main/delete_old_cluster.sh
7. Uruchamiamy nowy klaster:
$ pg_ctrlcluster 9.0 start
$ pg_lsclusters
Version Cluster Port Status Owner Data directory Log file
8.4 main 5432 down postgres /var/lib/postgresql/8.4/main /var/log/postgresql/postgresql-8.4-main.log
9.0 main 5433 online postgres /var/lib/postgresql/9.0/main /var/log/postgresql/postgresql-9.0-main.log
8. Dokonujemy czynności poinstalacyjnych
$ PGCLUSTER=9.0/main bash analyze_new_cluster.sh
This script will generate minimal optimizer statistics rapidly
so your system is usable, and then gather statistics twice more
with increasing accuracy. When it is done, your system will
have the default level of optimizer statistics.
If you have used ALTER TABLE to modify the statistics target for
any tables, you might want to remove them and restore them after
running this script because they will delay fast statistics generation.
If you would like default statistics as quickly as possible, cancel
this script and run:
vacuumdb --all --analyze-only
Generating minimal optimizer statistics (1 target)
--------------------------------------------------
vacuumdb: odkurzenie bazy danych "postgres"
vacuumdb: odkurzenie bazy danych "quaker"
vacuumdb: odkurzenie bazy danych "template1"
The server is now available with minimal optimizer statistics.
Query performance will be optimal once this script completes.
Generating medium optimizer statistics (10 targets)
---------------------------------------------------
vacuumdb: odkurzenie bazy danych "postgres"
vacuumdb: odkurzenie bazy danych "quaker"
vacuumdb: odkurzenie bazy danych "template1"
Generating default (full) optimizer statistics (100 targets?)
-------------------------------------------------------------
vacuumdb: odkurzenie bazy danych "postgres"
vacuumdb: odkurzenie bazy danych "quaker"
vacuumdb: odkurzenie bazy danych "template1"
Done
$ rm /var/lib/postgresql/9.0/main/postgresql.conf
Dodatkowo warto przeindeksować całą bazę danych - albo poprzez użycie pg_reorg albo poprzez skrypt: http://www.depesz.com/2012/09/24/concurrent-reindex-of-all-indexes-in-database/
9. Uruchamiamy naszą aplikację - sprawdzamy czy wszystko nadal działa. Jeżeli zachodzi konieczność powrotu do starej wersji bazy czytaj niżej.
10. Jeżeli wszystko jest OK - kasujemy stary klaster
$ pg_dropcluster 8.4 main
$ rm /var/lib/postgresql/delete_old_cluster.sh
$ rm /var/lib/postgresql/analyze_new_cluster.sh
11. Powtarzamy operacje od punktu 2 dla upgrade 9.0 do 9.1 i 9.1 do 9.2.
Do pg_upgrade, można dodać parametr --link. Przyspieszy on znacznie upgrade, lecz uniemożliwi powrót do stanu sprzed upgrade, jeżeli nowy cluster zostanie uruchomiony (a pewnie tak będzie - w końcu po co robić upgrade?). Jeżeli jednak zależy nam na czasie (i miejscu na dysku) warto ten parametr dodać
Jeżeli nie dodaliśmy parametru --link to powrót do stanu sprzed upgrade jest prosty. Wystarczy usunąć postfix .old, który został dodany do pliku global/pg_control. Więcej: http://www.postgresql.org/docs/9.0/static/pgupgrade.html#AEN128003, punkt 14.
Update: w Ubuntu 10.04 nic nie trzeba robić z plikiem global/pg_control. Wystarczy po prostu uruchomić zatrzymany stary cluster.
Oczywiście nic nie stoi na przeszkodzie, aby od razu przejść z 8.4 na 9.2 - jedyne co trzeba pamiętać, to liczba zmian, które się nawarstwią pomiędzy kolejnymi wersjami bazy, do których trzeba przygotować aplikację.
Począwszy od PostgreSQL w wersji 9.1 moduły z contrib (np. hstore, intarray czy ltree) są dostępne w postaci rozszerzeń i "ładowane" do bazy danych poprzez wywołanie stosowanego CREATE EXTENSION. Jeżeli upgradowaliśmy bazę 8.4 lub 9.0 i korzystaliśmy z tych rozszerzeń wypada trochę posporzątać. W tym celu wydajemy dla każdego rozszerzenia polecenia CREATE EXTENSION będąc zalogowany jako superuser w bazie, którą poprawiamy (DB):
# su - postgres
$ psql DB
sql# CREATE EXTENSION hstore WITH SCHEMA public FROM unpackaged;
sql# CREATE EXTENSION intarray WITH SCHEMA public FROM unpackaged;
sql# CREATE EXTENSION ltree WITH SCHEMA public FROM unpackaged;
Dodatkowo warto utworzyć osobny schemat i w nim trzymać rozszerzenia (poprawka: to jest dyskusyjne, bo nowy schemat wymaga jego wszędzie, ew. dopisania do search_path):
sql# CREATE SCHEMA extensions;
sql# ALTER EXTENSION hstore SET SCHEMA extensions;
sql# ALTER EXTENSION intarray SET SCHEMA extensions;
sql# ALTER EXTENSION ltree SET SCHEMA extensions;
W efekcie uzyskamy:
# \dx
List of installed extensions
Name | Version | Schema | Description
----------+---------+------------+--------------------------------------------------------------------
hstore | 1.1 | extensions | data type for storing sets of (key, value) pairs
intarray | 1.0 | extensions | functions, operators, and index support for 1-D arrays of integers
ltree | 1.0 | extensions | data type for hierarchical tree-like structures
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
(4 rows)
Jest jedno ale - jeżeli korzystaliśmy z bazy 8.4 możemy zobaczyć podczas wykonywania CREATE EXTENSION dla hstore coś takiego:
ERROR: function hstore_recv(internal) does not exist
Już wyjaśniam o co chodzi. W 9.0 moduł hstore przeszedł duży lifting. Zmieniła się też lista funkcji jakie są tworzone podczas jego ładowania. Jedną z tych funkcji jest hstore_recv. Aby wszystko doprowadzić do ładu i zwiększyć efektywność odczytu danych (nowy moduł zna stary format danych, lecz odczytuje je "wolniej") należy wykonać następujące polecenia:
Dla 9.1:
$ su - postgres
$ cat /usr/share/postgresql/9.1/extension/hstore--1.0.sql | tail -n +6 | sed -e 's/MODULE_PATHNAME/$libdir\/hstore/' | PGCLUSTER=9.1/main psql DB
$ PGCLUSTER=9.1/main psql DB
sql# update pg_type set typreceive = 'hstore_recv', typsend = 'hstore_send' where typname = 'hstore';
sql# \q
$ echo "select 'ALTER TABLE '||table_schema||'.'||table_name||' ALTER '||column_name||' TYPE hstore USING ' || column_name || ' || '''';' from information_schema.columns where udt_name = 'hstore'" | PGCLUSTER=9.1/main psql -t DB | PGCLUSTER=9.1/main psql -e DB
$ exit
Dla 9.2:
$ su - postgres
$ cat /usr/share/postgresql/9.2/extension/hstore--1.1.sql | tail -n +6 | sed -e 's/MODULE_PATHNAME/$libdir\/hstore/' | PGCLUSTER=9.2/main psql DB
$ PGCLUSTER=9.2/main psql DB
sql# update pg_type set typreceive = 'hstore_recv', typsend = 'hstore_send' where typname = 'hstore';
sql# \q
$ echo "select 'ALTER TABLE '||table_schema||'.'||table_name||' ALTER '||column_name||' TYPE hstore USING ' || column_name || ' || '''';' from information_schema.columns where udt_name = 'hstore'" | PGCLUSTER=9.2/main psql -t DB | PGCLUSTER=9.2/main psql -e DB
$ exit
Jak znajdę czas, to opisze sposób moje przygody związane z migracją dość dużej bazy danych z 8.4 na 9.2. Po migracji chciałbym skorzystać z dobrodziejstw CREATE EXTENSION i poprzenosić rzeczy związane z dodatkami (hstore, intarray) do oddzielnego schematu (extensions). Zobaczymy co wyjdzie.