Disclaimer

Showing posts with label PostgreSQL. Show all posts
Showing posts with label PostgreSQL. Show all posts

Sunday, 15 November 2020

How to resolve the problem of the pg_wal location running out of disk space?

How to resolve the problem of the pg_wal location (once known as pg_xlog) running out of disk space?

 

Transaction logs are a core component of all modern Relational Database Management Systems. They are designed to deliver improved performance.

PostgreSQL refers to these transaction logs as Write Ahead Logs (WAL).

By writing transaction information out to these logs, PostgreSQL is able to return control to the client before needing to perform the time-consuming task of persisting data changes to disk; and at the same time retaining the ability to restore a consistent database in the event of failure.

To do this, it is critical that PostgreSQL is able to read and modify the transaction logs at all times. So should a situation arise where PostgreSQL is not able to access the transaction log, the only option it has is to shut itself down as cleanly and as quickly as possible and wait until a DBA fixes the cause of the problem.

PostgreSQL by default stores its transaction logs in the pg_wal folder of the data directory (Note: older versions of PostgreSQL used a folder called pg_xlog – this folder was renamed in version 10 to emphasise the importance of the file within).

All changes made to the database are first written to the transaction log before anything else can occur. When the pg_wal directory fills up and no new files can be created, your database will likely shut down and create a state where it can't be brought up again.

You will see the following messages after this problem arises.

WARNING:  terminating connection because of crash of another server process

DETAIL:  The postmaster has commanded this server process to roll back the current transaction and exit because another server process exited abnormally and possibly corrupted shared memory.

HINT:  In a moment you should be able to reconnect to the database and repeat your command. server closed the connection unexpectedly This probably means the server terminated abnormally before or while processing the request. The connection to the server was lost. Attempting reset: Failed.

 

  

Trying to connect a new session will result in this error:

-bash-4.2$ psql -p 5438 postgres psql: could not connect to server: No such file or directory

        Is the server running locally and accepting

        connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5448"?

 

Resolving the situation

This situation can be resolved by following one of two simple approaches described below. The first approach is reactive as it explains what to do once the situation has already occurred. The second is a more proactive approach and outlines a number of steps to avoid the situation occurring in the first place:

The database won't start due to the disk on which the WAL is stored becoming full.

 

This problem could be caused by a number of things:

Problemà1) Check whether the archiving is functioning properly.

Do this by ensuring the archive command is set correctly and the concerned directory has the required permissions.

If the WAL archiving option is in use, old WAL segments cannot be removed or recycled until they are archived. If WAL archiving cannot keep up with the pace that WAL files are generated, or if the archive_command fails repeatedly, old WAL logs will accumulate until the archiving issue is resolved.

The PostgreSQL logs will give you a pretty clear indication of the problem (for example, in the log snippet shown below the archive_command is failing repeatedly). The log will look similar to below:

sh: /archive/ist5/arc/0000000400000028000000CD: No such file or directory
LOG:  archive command failed with exit code 1 (11263)
DETAIL: The failed archive command was: gzip < pg_wal/0000000400000028000000CD >/archive/ist5/arc/0000000400000028000000CD (14792)
PANIC:  could not write to file "pg_wal/waltemp.4111": No space left on device
LOG:  server process (PID 4111) was terminated by signal 6: Aborted (11206)
LOG:  terminating any other active server processes (11203)
LOG:  archiver process (PID 4103) exited with exit code 1 (11204)
LOG:  connection received: host=[local] (11213)

FATAL:  the database system is in recovery mode (11191)
LOG:  all server processes terminated; reinitializing (11210)
LOG:  database system was interrupted; last known up at 2017-10-04 01:15:41 GMT
LOG: database system was not properly shut down; automatic recovery in progress
LOG:  redo starts at 29/8D242168 (10126)
LOG:  redo done at 29/9BFFFF88 (10127)
LOG:  checkpoint starting: end-of-recovery immediate
PANIC:  could not write to file "pg_wal/waltemp.4920": No space left on device
LOG:  startup process (PID 4920) was terminated by signal 6: Aborted (11206)
LOG:  aborting startup due to startup process failure (11201)

 

Steps to resolve an archiving issue:

P1-A. Thoroughly read the PostgreSQL documentation on how to set up archiving. This high-quality documentation has all the information required to properly set up archiving.

P1-B. pg_wal holds WAL files for the archiver to archive and hence is not deleting them, this will result in a disk full issue.

Once archiving is set-up properly, start PostgreSQL (pg_ctl start –D data_directory ) and PostgreSQL will automatically start catching up. All the WAL logs that are not required will be recycled which will free up space in pg_wal directory.

You can see this is the PostgreSQL log as shown below:

DETAIL: The failed archive command was: gzip pg_wal/00000004000000290000000A /archive/inst5/arc/00000004000000290000000A

gzip: stdout: No space left on device

LOG: checkpoint complete: wrote 0 buffers (0.0%); 0 transaction log file(s) added, 58 removed, 3 recycled; write=0.001 s, sync=0.000 s, total=0.170 s; sync files=0, longest=0.000 s, average=0.000 s; distance=0 kB, estimate=0 kB

LOG: checkpoint starting: time

LOG: checkpoint complete: wrote 0 buffers (0.0%); 0 transaction log file(s) added, 113 removed, 1 recycled; write=0.000 s, sync=0.000 s, total=0.181 s; sync files=0, longest=0.000 s, average=0.000 s; distance=0 kB, estimate=0 kB

*Note that, at this stage the database will not be available for normal operations.

 Problem à2)  If you do not have archiving in place (which is not recommended for any transactional databases) or archiving is working fine but you can see that pg_wal is full, try one of the following solutions.

Firstly, set pg_hba.conf (by commenting client connection entries or setting method=reject) so that connections cannot be made to the database whilst under maintenance. Don't forget to change it back when everything is back to normal.

P2-A. Add more space to the partition.
The quickest way to give more space to PostgreSQL is by adding more space to the partition where the pg_wal directory is located. However, this is only a solution when your O/S and file system is designed to allow resizing. If this is not possible then try the option B below.

P2-B. Move the pg_wal directory
Move the pg_wal directory to another partition with more space while the database is shut down. Then create a symbolic link pointing to a new location and restart the database. This is a fast and effective way of getting the database up and running to resolve the problem.

If needed, resize the original partition later where the pg_wal directory was located and follow the steps to put pg_wal back to original location.

Copy all WAL logs to new WAL location (e.g. /home/transaction/inst5/transactionlog).

cp -rf /database/inst5/pg_wal/* /home/transaction/inst5/transactionlog/

If possible, and you have space at some different mount point, then take a backup of pg_wal.

mv pg_wal /home/postgre/pg_wal_bkp

Since we have all the WAL logs at new location, create a symbolic link from pg_wal to the new location (/home/transaction/inst5/transactionlog).

ln -s /home/transaction/inst5/transactionlog/ pg_wal

Start PostgreSQL and check whether new WAL logs are being generated at the new location. If everything is working fine then you can safely delete the copy of pg_wal.

rm –fR /home/postgre/pg_wal_bkp

 

P2-C. A final way of getting space back to start PostgreSQL.

Assuming you have previously followed the proactive approach and have ONLY_DELETE_THIS_DUMMY_FILE_IN_A_POSTGRES_EMERGENCY file already in your pg_wal directory or on the same mount point.

Delete the abovementioned dummy file. This will free up some space in the pg_wal directory so you can bring up your database. In this way, we don't have to look for candidate WAL to be deleted to free up space (as we are doing in the next step).

Do a checkpoint after bringing it up. Ideally, the checkpoint should start to recycle unused WAL logs. Sometimes it happens that even after issuing a checkpoint, space will not be freed up. In that case, you need to follow the next step together with this step.

rm ONLY_DELETE_THIS_DUMMY_FILE_IN_A_POSTGRES_EMERGENCY
psql –d postgres
checkpoint;

Note: When everything is back to normal, don't forget to recreate this file in case you want to use it in future.

P2-D. If the above steps are not possible then follow this final option.

Our priority is to find the WAL log where the checkpoint is writing currently. We can't use commands like pg_current_wal_lsn() as the database is not accessible at the moment. Instead, use the following command and look for Latest checkpoint's REDO WAL file (e.g. 000000010000000F00000026)

pg_controldata -D /database/inst5
Database system identifier:                      6465070279055498266
Database cluster state:                          in production
pg_control last modified:                        Wed 13 Sep 2017 12:07:38 AEST
Latest checkpoint location:                      0/F826ACC8
Prior checkpoint location:                       0/F8266088
Latest checkpoint's REDO location:               0/F826ACC8
Latest checkpoint's REDO WAL file:               000000010000000F00000026

*where D is the PGDATA directory path.

Now we know the latest WAL so we can safely use it to remove all files older than WAL file name 000000010000000F00000026 using the pg_archivecleanup command in the pg_wal directory. It is always safe to execute a dry run (with option –n) first and then use
–d option to delete them later.

pg_archivecleanup -n /home/transaction/inst5/transactionlog 000000010000000F00000026

pg_archivecleanup -d /home/transaction/inst5/transactionlog 000000010000000F00000026

Once deleted, you can start the database and you will also notice that pg_wal gets space back.
Note: Once you have done all of the above, you should take a fresh backup of your cluster.

 

A proactive approach to avoid this situation:

  1. Have a proper backup of the cluster.

  2. Proper and periodic database and database server health check.

  3. Backup pg_wal regularly and free up space. Set email alerts for disk space utilisation according to set thresholds (70%, 90% disk full etc.) and react immediately to avoid this situation.

  4. Backup archives regularly. If archive storage size is a concern, you can use gzip to compress the archive logs:


archive_command = 'gzip < %p > /archive_dir/%f'

* Note: You will then need to use gunzip during recovery, like below:

restore_command = 'gunzip < /mnt/server/archivedir/%f > %p'

  1. Make a dummy file of some specific size (eg 300MB) using the following command in a pg_wal directory or anywhere else on the same disk mount point.

Sometimes, this file is very handy to have when we need the space back to get PostgreSQL running after a disk full issue. Note there is no need to find and delete candidate WAL logs as the first approach. While having a dummy file is not mandatory, it's good to be able to free up a little work space when you need it:


dd if=/dev/zero of=/database/inst5/pg_wal/
ONLY_DELETE_THIS_DUMMY_FILE_IN_A_POSTGRES_EMERGENCY  bs=1MB count=300

 

PostgreSQL commands

PostgreSQL commands :-  



Most of cases you can use '+' to display more information for same command.

e.f.

\dt (display table information)

\dt+ ( display table information with addition columns)





Monday, 2 November 2020

Upgrade from PostgreSQL 10 to PostgreSQL 11

 

Scenario:

 

Cluster is running on RHEL 7 OS and current PostgreSQL version is 10, we will upgrade from 10 to 11.

 

Step1) Shutdown the both PostgreSQL instances

 

Step2) Check the pg_hba.conf file and add the below entries

 

# "local" is for Unix domain socket connections only

local   all             all                                     trust

 

 

Step3) Run the below command for upgradation but -c can be used to check the upgradation status before starting actual upgrade.

 

 

-bash-4.2$ /u02/PostgreSQL/11/11/bin/pg_upgrade -d /u02/PostgreSQL/10/data1_10ver -D /u02/PostgreSQL/11/data/ -b /u02/PostgreSQL/10/bin/ -B /u02/PostgreSQL/11/11/bin/ -c

 

Some information regarding the flags used above:
 
-b (--old-bindir=bindir) is the old cluster executable directory
 
-B (--new-bindir=bindir) is the new cluster executable directory
 
-d (--old-datadir=configdir) is the old cluster data directory
 
-D (--new-datadir=configdir) is the new cluster data directory
 
-k (--link)links instead of copying files to the new cluster NOTE: remove this option if you need to keep a local copy of the old cluster's data files. This will increase the time it takes the upgrade to run as well as the size of the cluster on disk. You can NOT go back after using -k. Please be sure that you have enough disk space for 2 whole copies of the cluster if you do NOT use the -k flag.
 
-c (--check) does a "check" only, and doesn't change any data. It will run through numerous consistency checks. Always run your pg_upgrade command with this first.
 
Additional information regarding pg_upgrade can be found in the documentation.

 

 

 

/u02/PostgreSQL/11/11/bin/pg_upgrade -d /u02/PostgreSQL/10/data1_10ver -D /u02/PostgreSQL/11/data/ -b /u02/PostgreSQL/10/bin/ -B /u02/PostgreSQL/11/11/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 reg* data types in user tables                 ok
Checking for contrib/isn with bigint-passing mismatch       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

 

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 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
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
 
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

 

 

 

-bash-4.2$

-bash-4.2$

 

Note: Once upgradation is completed successfully, it will create two scripts analyze_new_cluster.sh and delete_old_cluster.sh

 

 

Step4) Start the PostgreSQL instance

 

-bash-4.2$ /u02/PostgreSQL/11/11/bin/pg_ctl -D /u02/PostgreSQL/11/data start

waiting for server to start....2020-03-30 20:20:17.242 IST [62864] LOG:  listening on IPv4 address "127.0.0.1", port 5555

2020-03-30 20:20:17.248 IST [62864] LOG:  listening on Unix socket "/tmp/.s.PGSQL.5555"

2020-03-30 20:20:17.263 IST [62865] LOG:  database system was shut down at 2020-03-30 20:17:29 IST

2020-03-30 20:20:17.268 IST [62864] LOG:  database system is ready to accept connections

 done

server started

 

 

Step5) Login to psql prompt and check the version

 

-bash-4.2$ psql -p 5555

psql (10.9, server 11.7)

WARNING: psql major version 10, server major version 11.

         Some psql features might not work.

Type "help" for help.

 

postgres=#

postgres=#

postgres=# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 ganga     | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 sandeep   | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | postgres=CTc/postgres+
           |          |          |             |             | =c/postgres
(5 rows)
 
postgres=# select version();
                                   version
-----------------------------------------------------------------------------
 PostgreSQL 11.7 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 5.5.0, 64-bit
(1 row)
 

postgres=#

 

 

-bash-4.2$ pwd

/u02/PostgreSQL/10

 

-bash-4.2$ ls -lrt
total 604
drwxr-xr-x.  6 postgres postgres   4096 Aug  9  2019 include
drwxr-xr-x. 11 postgres postgres   4096 Aug  9  2019 share
drwxr-xr-x.  2 postgres postgres   4096 Aug  9  2019 bin
drwxr-xr-x.  7 postgres postgres  12288 Aug  9  2019 lib
-rw-r--r--.  1 postgres postgres   6441 Aug  9  2019 README-linux-x64.txt
-rw-------.  1 postgres postgres 567738 Aug  9  2019 install.log
drwx------  20 postgres postgres   4096 Mar 30 19:25 data
drwx------  19 postgres postgres   4096 Mar 30 20:17 data1_10ver
-rwx------   1 postgres postgres     51 Mar 30 20:17 delete_old_cluster.sh
-rwx------   1 postgres postgres    769 Mar 30 20:17 analyze_new_analyze_new_clustercluster.sh
 
 
 
 
-bash-4.2$ ./analyze_new_cluster.sh -p 5555
 
 
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:

    "/u02/PostgreSQL/11/11/bin/vacuumdb" --all --analyze-only

 

vacuumdb: could not connect to database template1: could not connect to server: No such file or directory

        Is the server running locally and accepting

        connections on Unix domain socket "/tmp/.s.PGSQL.5432"?

 

 
export PATH=/u02/PostgreSQL/11/11/bin:$PATH
export PGDATA=/u02/PostgreSQL/11/data
export PGDATABASE=postgres
export PGUSER=postgres
export PGPORT=5555
 
 
-bash-4.2$ cat .bash_profile1
export PATH=/u02/PostgreSQL/11/11/bin:$PATH
export PGDATA=/u02/PostgreSQL/11/data
export PGDATABASE=postgres
export PGUSER=postgres
export PGPORT=5555
-bash-4.2$
-bash-4.2$
-bash-4.2$

 

analyze_new_cluster.sh ==> script in order to generate stats so the system is usable.

 

 

-bash-4.2$ ./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:
    "/u02/PostgreSQL/11/11/bin/vacuumdb" --all --analyze-only
 
vacuumdb: processing database "ganga": Generating minimal optimizer statistics (1 target)
vacuumdb: processing database "postgres": Generating minimal optimizer statistics (1 target)
vacuumdb: processing database "sandeep": Generating minimal optimizer statistics (1 target)
vacuumdb: processing database "template1": Generating minimal optimizer statistics (1 target)
vacuumdb: processing database "ganga": Generating medium optimizer statistics (10 targets)
vacuumdb: processing database "postgres": Generating medium optimizer statistics (10 targets)
vacuumdb: processing database "sandeep": Generating medium optimizer statistics (10 targets)
vacuumdb: processing database "template1": Generating medium optimizer statistics (10 targets)
vacuumdb: processing database "ganga": Generating default (full) optimizer statistics
vacuumdb: processing database "postgres": Generating default (full) optimizer statistics
vacuumdb: processing database "sandeep": Generating default (full) optimizer statistics
vacuumdb: processing database "template1": Generating default (full) optimizer statistics
 
Done
 
 
 
-bash-4.2$ ls -lrt
total 604
drwxr-xr-x.  6 postgres postgres   4096 Aug  9  2019 include
drwxr-xr-x. 11 postgres postgres   4096 Aug  9  2019 share
drwxr-xr-x.  2 postgres postgres   4096 Aug  9  2019 bin
drwxr-xr-x.  7 postgres postgres  12288 Aug  9  2019 lib
-rw-r--r--.  1 postgres postgres   6441 Aug  9  2019 README-linux-x64.txt
-rw-------.  1 postgres postgres 567738 Aug  9  2019 install.log
drwx------  20 postgres postgres   4096 Mar 30 19:25 data
drwx------  19 postgres postgres   4096 Mar 30 20:17 data1_10ver----------------------------This directory will be removed once below command is executed
-rwx------   1 postgres postgres     51 Mar 30 20:17 delete_old_cluster.sh
-rwx------   1 postgres postgres    769 Mar 30 20:17 analyze_new_cluster.sh
-bash-4.2$ pwd
/u02/PostgreSQL/10
-bash-4.2$
-bash-4.2$ cat delete_old_cluster.sh
#!/bin/sh
 
rm -rf '/u02/PostgreSQL/10/data1_10ver'
-bash-4.2$
-bash-4.2$
-bash-4.2$ ./delete_old_cluster.sh
-bash-4.2$
-bash-4.2$ cd /u02/PostgreSQL/10/
-bash-4.2$ ls -lrt
total 600
drwxr-xr-x.  6 postgres postgres   4096 Aug  9  2019 include
drwxr-xr-x. 11 postgres postgres   4096 Aug  9  2019 share
drwxr-xr-x.  2 postgres postgres   4096 Aug  9  2019 bin
drwxr-xr-x.  7 postgres postgres  12288 Aug  9  2019 lib
-rw-r--r--.  1 postgres postgres   6441 Aug  9  2019 README-linux-x64.txt
-rw-------.  1 postgres postgres 567738 Aug  9  2019 install.log
drwx------  20 postgres postgres   4096 Mar 30 19:25 data
-rwx------   1 postgres postgres     51 Mar 30 20:17 delete_old_cluster.sh
-rwx------   1 postgres postgres    769 Mar 30 20:17 analyze_new_cluster.sh
-bash-4.2$
 
-bash-4.2$ psql
psql.bin (11.7)
Type "help" for help.
 
postgres=#
postgres=#
 
-bash-4.2$ pwd
/u02/PostgreSQL/11
 
-bash-4.2$ ls -lrt
total 6952
drwx------  3 postgres postgres    4096 Mar 30 18:49 rollbackBackupDirectory
drwx------  3 postgres postgres    4096 Mar 30 18:51 OmniDB
drwx------  4 postgres postgres    4096 Mar 30 18:51 pl-languages
-rwx------  1 postgres postgres 6946528 Mar 30 18:52 Uninstall11
-rwx------  1 postgres postgres  138094 Mar 30 18:52 Uninstall11.dat
drwx------  6 postgres postgres    4096 Mar 30 18:54 11
-rw-------  1 postgres postgres     358 Mar 30 20:04 pg_upgrade_utility.log
-rw-------  1 postgres postgres    1315 Mar 30 20:04 pg_upgrade_internal.log
-rw-------  1 postgres postgres    3459 Mar 30 20:04 pg_upgrade_server.log
drwx------ 19 postgres postgres    4096 Mar 30 20:20 data
 
 
-bash-4.2$ pwd
/u02/PostgreSQL/11/data/pg_hba.conf
 
# TYPE  DATABASE        USER            ADDRESS                 METHOD
 
# "local" is for Unix domain socket connections only
local   all             all                                     trust
local   all             all                                     md5
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 md5
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     md5
host    replication     all             127.0.0.1/32            md5
host    replication     all             ::1/128                 md5
 
 
 

 

Undo Queries

  SQL> SQL> select sum(bytes /(1024*1024*1024)) from dba_undo_extents where status='EXPIRED'; select sum(bytes /(1024*1024*102...