Företag och företag som använder gamla versioner av PostgreSQL (PG) möter utmaningar när de uppgraderar till åtminstone den senaste stabila versionen från PostgreSQL 12 eller PostgreSQL 13. Det finns många anledningar till att uppgradering till den senaste versionen är en måste. Några av huvudskälen till detta är att dra nytta av dess kritiska förbättringar av dess inbyggda funktioner, säkerhetsuppdateringar, prestandaförbättringar och nya implementeringar som är fördelaktiga för databashantering.
Att uppgradera PostgreSQL kommer med några utmaningar eftersom det inte är lika lätt jämfört med andra vanliga databaser. Om du står inför den här typen av problem, oroa dig inte. PostgreSQL låser dig inte på en specifik version att använda. I den här bloggen går vi igenom ett exempel på denna utmaning samtidigt som vi har en TimescaleDB och PostGIS installerade på en befintlig PostgreSQL 11-värd.
Varför pg_upgrade?
pg_upgrade har funnits väldigt länge som ett verktyg för att uppgradera större versioner av PostgreSQL. Att använda det här verktyget krävs inte för mindre versionsuppgraderingar, vilket innebär att det inte är nödvändigt att uppgradera din nuvarande version av 11.9 till 11.13.
När du uppgraderar din PostgreSQL till en större version med pg_upgrade, fungerar verktyget genom att tillåta att data som lagras i PostgreSQL-datafiler uppgraderas till en senare PostgreSQL-huvudversion. Detta fungerar utan att behöva en datadumpning/reload, vilket kan ta lite tid om du har en stor datamängd.
Nu, här kommer väsen. PostgreSQL, särskilt för större versionsutgåvor, är känt för att ha nya funktioner som ofta ändrar layouten på systemtabellerna, men det interna datalagringsformatet ändras sällan. pg_upgrade använder detta faktum för att utföra snabba uppgraderingar genom att skapa nya systemtabeller och helt enkelt återanvända de gamla användardatafilerna. Om en framtida större utgåva någonsin ändrar datalagringsformatet på ett sätt som gör det gamla dataformatet oläsligt, kommer pg_upgrade inte att kunna användas för sådana uppgraderingar. (Gruppen kommer att försöka undvika sådana situationer.)
Vissa kanske anser att pg_upgrade är farligt, särskilt för produktionsmiljön. Tja, det här verktyget har använts i stor utsträckning på andra ställen, från QA, till dev, till produktionsmiljöer. Det har sina begränsningar eller varningar, till exempel den kända Unicode eller teckenuppsättningar som lagras i din datauppsättning. I så fall kan du överväga att använda pg_dump/pg_restore, men det kan ta lite tid att slutföra beroende på hur stor din data är. För nyare versioner av PostgreSQL, som PG 14.0, kan du bara ta en dump/återställning (eller export/import) eller logisk replikering, annars använd pg_upgrade.
För större datamängder kräver användning av pg_upgrade att du kör detta på samma värd, som som standard tillämpar en kopia av alla dina fysiska filer från din datakatalog. I så fall stöder pg_upgrade alternativen -k eller --link, vilket innebär att den kommer att använda hårda länkar istället för att kopiera filer till det nya klustret.
pg_upgrade gör sitt bästa för att se till att de gamla och nya klustren är binärkompatibla, t.ex. genom att leta efter kompatibla inställningar för kompileringstid, inklusive 32/64-bitars binärer. Det är också viktigt att alla externa moduler är binärkompatibla, även om detta inte kan kontrolleras av pg_upgrade.
pg_upgrade stöder uppgraderingar från 8.4.X och senare till den nuvarande stora versionen av PostgreSQL, inklusive snapshot- och betaversioner.
Så här är situationen...
I den här installationen använde jag ClusterControl för att distribuera ett PostgreSQL 11-databaskluster för en enda nod. Följande har testats på Centos 7 och Ubuntu Focal (20.04.1):
$ /usr/pgsql-11/bin/postgres --version
postgres (PostgreSQL) 11.13
postgres=# \dx
List of installed extensions
Name | Version | Schema | Description
------------------------+---------+------------+-------------------------------------------------------------------
fuzzystrmatch | 1.1 | public | determine similarities and distance between strings
pg_stat_statements | 1.6 | public | track execution statistics of all SQL statements executed
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
postgis | 3.1.4 | public | PostGIS geometry and geography spatial types and functions
postgis_raster | 3.1.4 | public | PostGIS raster types and functions
postgis_sfcgal | 3.1.4 | public | PostGIS SFCGAL functions
postgis_tiger_geocoder | 3.1.4 | tiger | PostGIS tiger geocoder and reverse geocoder
postgis_topology | 3.1.4 | topology | PostGIS topology spatial types and functions
timescaledb | 2.3.1 | public | Enables scalable inserts and complex queries for time-series data
(9 rows)
Så jag fick följande,
PostgreSQL-serverversion: 11.13
TimescaleDB version: 2.3.1
PostGIS-version: 3.1.4
Om du vill testa detta med ClusterControl finns det två sätt att ha TimescaleDB. Du kan distribuera ett TimescaleDB-kluster eller ha PostgreSQL och aktivera TimescaleDB-plugin.
Konfigurera för din PostgreSQL 13
Det är lättare att använda din pakethanterare för Linux-miljön med ditt PostgreSQL- och TimescaleDB-förråd. Här är stegen för att göra det:
Konfigurera de nödvändiga arkiven
Låt oss först lägga till PostgreSQL-förvaret.
För CentOS/RHEL/Oracle Linux
Du måste se till att du har rätt arkiv. För Enterprise Linux (EL) 7 kan du göra följande:
sudo yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
För annan arkitektur kan du basera här https://download.postgresql.org/pub/repos/yum/reporpms/ och ersätta underkatalogen EL-7-x86_64.
Låt oss lägga till TimescaleDB-förvaret också.
vi /etc/yum.repos.d/timescale_timescaledb.repo
Lägg sedan till följande innehåll för den här filen,
[timescale_timescaledb]
name=timescale_timescaledb
baseurl=https://packagecloud.io/timescale/timescaledb/el/7/\$basearch
repo_gpgcheck=1
gpgcheck=0
enabled=1
gpgkey=https://packagecloud.io/timescale/timescaledb/gpgkey
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300
Byt bara ut baseurl i enlighet med detta om du använder en annan version än EL 7.
För Ubuntu/Debian
Lägg till PG-förrådet för Ubuntu Focal:
deb http://apt.postgresql.org/pub/repos/apt/ focal-pgdg main
För andra Ubuntu/Debian-distributioner, byt bara ut fokalen i enlighet med detta, som du kan hitta här http://apt.postgresql.org/pub/repos/apt/dists/. Byt till exempel ut focal-pgdg med buster-pgdg.
Låt oss nu lägga till arkivet för TimescaleDB,
sudo sh -c "echo 'deb [signed-by=/usr/share/keyrings/timescale.keyring] https://packagecloud.io/timescale/timescaledb/ubuntu/ $(lsb_release -c -s) main' > /etc/apt/sources.list.d/timescaledb.list"
Importera nyckelringen,
wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/timescale.keyring
och uppdatera paketlistorna för uppgraderingar för paket som behöver uppgraderas, såväl som nya paket som precis har kommit till arkiven.
sudo apt-get update
Du kan ersätta underkatalogen i URL:en om du använder Debian från ubuntu.
Nu när vi har förvaret klart är vi igång.
Installera PostgreSQL version 13 med TimescaleDB och PostGIS
Installation av PostgreSQL 13 kan göras på samma värd. Först måste du se till att saker som databasporten är unika. Med andra ord måste den vara annorlunda än den nuvarande PostgreSQL 11 installerad på samma värd.
För CentOS/RHEL/Oracle Linux
Kör kommandot nedan för att installera PostgreSQL 13 och dess beroende paket:
yum install postgresql13.x86_64 postgresql13-server.x86_64 postgresql13-contrib.x86_64 postgresql13-libs.x86_64
Initiera sedan databasklustret och dess nödvändiga samling av databaser genom att köra kommandot nedan:
$ /usr/pgsql-13/bin/postgresql-13-setup initdb
Vid denna tidpunkt bör det finnas två datakataloger både för PG 11 och PG 13:
[[email protected] ~]# ls -alth /var/lib/pgsql/* -d
drwx------. 4 postgres postgres 51 Sep 22 14:19 /var/lib/pgsql/13
drwx------. 4 postgres postgres 33 Sep 21 18:53 /var/lib/pgsql/11
Nu när vi är bra med PostgreSQL 13 låt oss installera TimescaleDB. Vi måste se till att plugin-programmet som ska installeras är samma version på PostreSQL 11.
Observera att, för att säkerställa att pg_upgrade fungerar smidigt, bör plugin-programmen för din käll- och huvudversionsdestination vara samma version. Detta beror på att pg_upgrade kommer att leta efter dess utsedda bibliotek länkade till plugins eller tillägg som har laddats eller använts av din gamla eller källdatabasversion av din PostgreSQL. Du kan verifiera detta i din Enterprise Linux genom att köra showduplicates eller genom att verifiera med info precis som nedan antingen med dnf eller yum:
$ yum --showduplicates list timescaledb_13.x86_64 timescaledb-2-postgresql-13.x86_64 timescaledb-2-oss-postgresql-13.x86_64 timescaledb-2-loader-postgresql-13.x86_64|grep '2.3.1'
Repository pgdg-common is listed more than once in the configuration
timescaledb-2-loader-postgresql-13.x86_64 2.3.1-0.el7 timescale_timescaledb
timescaledb-2-oss-postgresql-13.x86_64 2.3.1-0.el7 timescale_timescaledb
timescaledb-2-postgresql-13.x86_64 2.3.1-0.el7 timescale_timescaledb
Eller verifiera det med infoalternativet:
$ yum info timescaledb-2-loader-postgresql-13-2.3.1-0.el7.x86_64 timescaledb-2-postgresql-13-2.3.1-0.el7.x86_64
Nu är vi redo att installera TimescaleDB-paketet för PG 13-versionen.
$ yum install timescaledb-2-loader-postgresql-13-2.3.1-0.el7.x86_64 timescaledb-2-postgresql-13-2.3.1-0.el7.x86_64
När du har installerat det kan du försöka köra timescaledb-tune-verktyget för att finjustera din postgresql.conf-konfigurationsfil. Kör bara kommandot nedan:
$ timescaledb-tune --pg-config=/usr/pgsql-13/bin/pg_config
Låt oss nu installera PostGIS-paketet för PG 13-versionen också.
$ yum install -y postgis31_13.x86_64
För Ubuntu/Debian
Kör helt enkelt:
$ apt install postgresql-client-13 postgresql-13
Det fantastiska med Ubuntu/Debian-distributioner är att det finns verktyg för PostgreSQL som är mycket praktiska för att hantera dina PostgreSQL-kluster, som pg_lsclusters, pg_ctlcluster, etc.
Du kan verifiera att dina tillgängliga kluster är installerade.
$ pg_lsclusters
Ver Cluster Port Status Owner Data directory Log file
11 main 5432 online postgres /var/lib/postgresql/11/main log/postgresql-%Y-%m-%d_%H%M%S.log
13 main 5433 online postgres /var/lib/postgresql/13/main /var/log/postgresql/postgresql-13-main.log
I Ubuntu/Debian finns det inget behov av att ändra porten eftersom den kommer att hanteras under installationsfasen och den upptäcker och ställer in den unikt i enlighet därmed.
Låt oss nu installera TimescaleDB.
$ apt install timescaledb-2-loader-postgresql-13 timescaledb-2-postgresql-13
Valfritt kan du köra timescaledb-tune-verktyget för att finjustera din postgresql.conf-konfigurationsfil genom att helt enkelt anropa verktyget enligt följande:
$ timescaledb-tune
Nu är vi redo att installera PostGIS-paketet för PG 13.
$ apt install postgresql-13-postgis-3-scripts postgresql-13-postgis-3
Granska din postgresql.conf
Det är alltid bättre att granska din postgresql.conf-konfigurationsfil. I Enterprise Linux-versioner kan du hitta din postgresql.conf antingen i din data_directory eller PGDATA-sökväg. Medan för Ubuntu/Debian kan du hitta den i /etc/postgresql/
shared_preload_libraries = 'pg_stat_statements,timescaledb' # pg_stat_statements is not required but if you are using ClusterControl, make sure this is appended.
port = 5532 # make sure that the port number is unique than the old version of your PostgreSQL
listen_address = * # depends on your setup but if you need to specify the available network interfaces to its IP addresses (IPv4 or IPv6) set it accordingly.
Det är bästa praxis att jämföra dina gamla och nya versioner av dina PostgreSQL-konfigurationsfiler för att säkerställa att din postgresql.conf är identisk med vad som behövs och ställs in.
Innan vi fortsätter med nästa steg måste vi också kontrollera att din PostgreSQL version 13 laddas i enlighet därmed. Se till att du har den senaste versionen förvärvad eller installerad i din värd. Starta databasen och se till att den startar och körs korrekt.
För att starta i EL-distributioner, kör kommandot nedan:
$ sudo -iu postgres /usr/pgsql-13/bin/pg_ctl -D /var/lib/pgsql/13/data/ -o "-c config_file=/var/lib/pgsql/13/data/postgresql.conf" start
eller för Ubuntu/Debian, kör kommandot nedan:
$ sudo -iu postgres /usr/lib/postgresql/13/bin/pg_ctl -D /var/lib/postgresql/13/main/ -o "-c config_file=/etc/postgresql/13/main/postgresql.conf" start
eller använd verktyget pg_ctlcluster för att starta, starta om eller stoppa ditt PG-kluster.
Kör pg_upgrade...
när du är klarInnan du går vidare, se först till att du alltid har din säkerhetskopia från din gamla server redo och tillgänglig. Ta alltid en logisk säkerhetskopia och fysisk säkerhetskopia som god praxis innan du fortsätter med en större uppgradering.
Nu när du är redo är du bra att köra pg_upgrade. I praktiken måste du först köra pg_upgrade med en kontroll för att fastställa inkompatibiliteten och problemen innan du fortsätter till huvudproceduren för pg_upgrade. Innan du kör pg_upgrade, se till att både PG 11 och PG 13 är nere medan du gör den här processen. Det betyder bara att driftstopp behövs för denna process.
För att göra det, kör följande kommando med --check alternativet:
$ sudo -iu postgres /usr/lib/postgresql/13/bin/pg_upgrade -o "-c config_file=/etc/postgresql/11/main/postgresql.conf" --old-datadir=/var/lib/postgresql/11/main/ -O "-c config_file=/etc/postgresql/13/main/postgresql.conf" --new-datadir=/var/lib/postgresql/13/main/ --old-bindir=/usr/lib/postgresql/11/bin --new-bindir=/usr/lib/postgresql/13/bin --check
Ersätt --old-datadir-värdet eller config_file i enlighet med detta om det skiljer sig från din inställning.
Detta ska köra kompatibilitetskontroller precis som resultatet nedan:
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 system-defined composite types in user tables ok
Checking for reg* data types in user tables ok
Checking for contrib/isn with bigint-passing mismatch ok
Checking for tables WITH OIDS ok
Checking for invalid "sql_identifier" user columns 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
*Clusters are compatible*
Om alla kontroller signalerar "ok" betyder det en lyckad kontroll, och det nedersta meddelandet visar att kluster är kompatibla, bör du vara igång.
Kör slutligen kommandot igen utan --check-alternativet:
$ sudo -iu postgres /usr/lib/postgresql/13/bin/pg_upgrade -o "-c config_file=/etc/postgresql/11/main/postgresql.conf" --old-datadir=/var/lib/postgresql/11/main/ -O "-c config_file=/etc/postgresql/13/main/postgresql.conf" --new-datadir=/var/lib/postgresql/13/main/ --old-bindir=/usr/lib/postgresql/11/bin --new-bindir=/usr/lib/postgresql/13/bin
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 system-defined composite types in user tables ok
Checking for reg* data types in user tables ok
Checking for contrib/isn with bigint-passing mismatch ok
Checking for tables WITH OIDS ok
Checking for invalid "sql_identifier" user columns 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
------------------
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 cluste ok
Copying user relation files ok
Setting next OID for new cluster ok
Sync data directory to disk ok
Creating script to analyze new cluster ok
Creating script to delete old cluster ok
Checking for extension updates notice
Your installation contains extensions that should be updated
with the ALTER EXTENSION command. The file
update_extensions.sql
when executed by psql by the database superuser will update
these extensions.
Upgrade Complete
----------------
Optimizer statistics are not transferred by pg_upgrade so,
once you start the new server, consider running:
./analyze_new_cluster.sh
Running this script will delete the old cluster's data files:
./delete_old_cluster.sh
Beroende på storleken på din datauppsättning kan det ta lite tid. I exempelkommandot ovan kopierar den transaktionsloggarna, som är av fysiska filer. Men om din diskstorlek är knapp kan du använda alternativet -k eller --link, som använder hårda länkar. Om allt går som det ska bör den ge dig meddelanden som ovan som meddelar dig om fullständig uppgradering och meddelanden om att uppdatera tilläggen du kan ha. I den här inställningen går det smidigt. Update_extensions.sql innehåller endast följande:
$ cat update_extensions.sql
\connect postgres
ALTER EXTENSION "pg_stat_statements" UPDATE;
Som du märkte gör pg_upgrade en rad åtgärder. Den analyserar alla rader från källklustret, kopierar transaktionsmetadataloggar och dess multitransaktionsstatusdata och resten.
När du har kommit på att allt ser bra ut kör du skriptet analyze_new_cluster.sh, som ska köras
vacuumdb --all --analyze-only.
$ sudo -iu postgres PGPORT=5433 ./analyze_new_cluster.sh
Observera att du bör ange porten för din PostgreSQL 13 så att vacuumdb körs korrekt till rätt målserver.
I det här fallet går uppgraderingsresultatet med TimescaleDB och PostGIS-tillägg aktiverade bra. När allt visas i ordning, se till att starta servern och göra en rad tester och kontroller.
Testa uppgraderingsprocessen
Testa och granska alltid uppgraderingsprocessen. Här är några tabeller och en användardefinierad databas, som innehåller hypertabeller och PostGIS-tabeller som förlitar sig på att använda geometri och geografi rumsliga typer och funktioner.
$ sudo -iu postgres psql -p5433
psql (13.4 (Ubuntu 13.4-1.pgdg20.04+1))
Type "help" for help.
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+---------+---------+-----------------------
mydb | postgres | UTF8 | C.UTF-8 | C.UTF-8 |
postgres | postgres | UTF8 | C.UTF-8 | C.UTF-8 |
template0 | postgres | UTF8 | C.UTF-8 | C.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | C.UTF-8 | C.UTF-8 | postgres=CTc/postgres+
| | | | | =c/postgres
(4 rows)
postgres=# \c mydb
You are now connected to database "mydb" as user "postgres".
mydb=# set search_path="$user",public;
SET
mydb=# \dt+
List of relations
Schema | Name | Type | Owner | Persistence | Size | Description
--------+-----------------+-------+----------+-------------+------------+-------------
public | conditions | table | postgres | permanent | 8192 bytes |
public | global_points | table | postgres | permanent | 16 kB |
public | roads | table | postgres | permanent | 16 kB |
public | sample_table | table | postgres | permanent | 8192 bytes |
public | spatial_ref_sys | table | postgres | permanent | 6968 kB |
(5 rows)
Kontrollerar några av mina PostGIS och hypertabeller:
mydb=# \d roads
Table "public.roads"
Column | Type | Collation | Nullable | Default
------------+----------------------+-----------+----------+---------
road_id | integer | | |
road_name | character varying | | |
roads_geom | geometry(LineString) | | |
mydb=# \d sample_table
Table "public.sample_table"
Column | Type | Collation | Nullable | Default
--------+--------------------------+-----------+----------+------------------------------------------
id | integer | | not null | nextval('sample_table_id_seq'::regclass)
time | timestamp with time zone | | not null |
name | character varying | | not null |
Indexes:
"sample_table_pkey" PRIMARY KEY, btree (id, "time")
"sample_table_time_idx" btree ("time" DESC)
Triggers:
ts_insert_blocker BEFORE INSERT ON sample_table FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
Number of child tables: 371 (Use \d+ to list them.)
mydb=# \d conditions
Table "public.conditions"
Column | Type | Collation | Nullable | Default
-------------+--------------------------+-----------+----------+---------
time | timestamp with time zone | | not null |
location | text | | not null |
location2 | character(10) | | not null |
temperature | double precision | | |
humidity | double precision | | |
Indexes:
"conditions_time_idx" btree ("time" DESC)
Triggers:
ts_insert_blocker BEFORE INSERT ON conditions FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
Number of child tables: 366 (Use \d+ to list them.)
mydb=# select count(*) from sample_table;
count
-------
2588
(1 row)
mydb=# SELECT name FROM global_points WHERE ST_DWithin(location, 'SRID=4326;POINT(-110 29)'::geography, 1000000);
name
--------
Town
Forest
(2 rows)
mydb=# SELECT n, ST_AsEWKT(ST_GeometryN(the_geom, n)) As geomewkt
mydb-# FROM (
mydb(# VALUES (ST_GeomFromEWKT('MULTIPOINT(1 2 7, 3 4 7, 5 6 7, 8 9 10)') ),
mydb(# ( ST_GeomFromEWKT('MULTICURVE(CIRCULARSTRING(2.5 2.5,4.5 2.5, 3.5 3.5), (10 11, 12 11))') )
mydb(# )As foo(the_geom)
mydb-# CROSS JOIN generate_series(1,100) n
mydb-# WHERE n <= ST_NumGeometries(the_geom);
n | geomewkt
---+-----------------------------------------
1 | POINT(1 2 7)
1 | CIRCULARSTRING(2.5 2.5,4.5 2.5,3.5 3.5)
2 | POINT(3 4 7)
2 | LINESTRING(10 11,12 11)
3 | POINT(5 6 7)
4 | POINT(8 9 10)
(6 rows)
Nu ser allt ut att vara redo att fungera som mitt nya kluster.
När du har fått igång saker och ting kan du köra:
$ sudo -iu postgres ./delete_old_cluster.sh
Se till att du bara kör skriptet eftersom detta är ett mycket farligt skript, eftersom det tar bort alla filer i ditt gamla PostgreSQL-kluster.
Slutsats
pg_upgrade är ett så bra verktyg för att hantera och uppgradera din PostgreSQL-databasserver. Den kan hantera komplexa inställningar som med TimescaleDB eller PostGIS-tillägg aktiverade. Även om det här verktyget har sina begränsningar finns det ingen hejd på att använda det, särskilt för ditt DBA-arbete och på produktionsservrar förutom QA och utvecklingsmiljöer.