Postgres Notes
Postgres Notes
What is PostgreSQL
PostgreSQL Limits
What is Page
The data stored on disk is called Page , but while reading the data it is
fetched back to memory , so the data loaded back in the memory is
called Buffer.
• Page Header (24 byte Long) – Keeps information about free space ,
page size and version.
If insertion performed , database will check the availability of space
in page header. Depending on the availability it stores the tuple or it
will move to the next page.
• Item Data ID (4 bytes per item) – Array of pairs pointing to the
actual item or tuples.
• Free Space – Un-allocated space. New item pointers are allocated
from the start of this area and new item from the end.
Module Objective:
Hardware Requirements:
• 1 GHz processor
• 2 GB of RAM
• 512 MB of HDD
Software Requirements:
Steps 1:
Navigate to www.postgresql.org/downloads
Step 5: Right click on the setup file and select “Run as Administrator”
Step 8: Search for psql interface from the start menu and try to connect to
Postgresql.
Step 1: Click on Start -> Search for This PC/My PC -> Right click on This
PC -> Select Properties -> Advanced -> Environment Variables.
Step 4: Click new and copy the location of postgresql bin folder in the new
line and click ok.
Step 5: Click option New in the system variable and enter variable name
as “PGDATA” and variable value as location of the postgresql data
directory.
Step 6: Select okay in all open windows to save & exit out of Environment
variable.
Step 8: Install the downloaded rpm using the following syntax on the linux
box:
rpm -ivh pgdg-redhat-repo-42.0-11.noarch.rpm
Step 10: Type the following command to list all available postgresql
version.
$ Yum list module postgresql*
PostgreSQL Architecture
Assume the scenario , user sends SELECT request , data loaded from the
datafiles into the shared buffer and the results are sent back to the client by
the postgres process.
Windows : Goto taskbar > Right Click >> Open Task Manager , All OS
running processes will be displayed . Write click on status and add column
“Command Line”. You can see the all processes associated with postgres.
If one process is killed postmaster will restart the killed process.
Linux :
• Wal Writer : Write the WAL buffer to the WAL file when the
commit request received.
Shared Buffer :
• User cannot access the datafile directly to read or write any data.
• Any select, insert, update or delete to the data is done via shared
buffer area.
• The data that is written or modified in this location is called “Dirty
data“.
• Dirty data is written to the data files located in physical disk through
background writer process.
Wal Buffer:
• CLOG stands for "commit log", and the CLOG buffers is an area in
operating system RAM dedicated to hold commit log pages.
• The commit logs have commit status of all transactions and indicate
whether or not a transaction has been completed (committed).
• Wal Files : Write ahead log file, where all committed transactions
are written first here before writing to datafile.
• Log Files: All server messages, including stderr, csvlog and syslog
are logged in log files.
Database Clusters
Database Cluster:
• Database cluster is a collection of databases that is managed by
a single instance on a server.
initdb -D /usr/local/pgsql/data
-W = we can use this option to force the super user to provide password
before initialize db
Start\Stop Cluster:
• Start Cluster Syntax :
Linux : systemctl start postgresql-<Ver>
Windows : pg_ctl –D “C:\Program Files\PostgreSQL\12\data”
start
• Stop Cluster Syntax :
Linux : systemctl stop postgresql-<Ver>
Windows : : pg_ctl stop -D “C:\Program Files\PostgreSQL\12\
data” –m shutdown mode
Fast :(SIGINT Default) : The server disallows new connections and abort
their current transactions and exits gracefully.
• Reload will just reload the new configurations, without restarting the
service.
Reload\Restart Cluster:
Pg_Controldata
PATH="/usr/lib/postgresql/13/bin/:$PATH
FULL Output:
Base_Directory:
• Contains databases, that represented as directories named after their
object identifier (OID) not by the database name. Database name and
OID mapping can be found on pg_database table.
Postgresql.conf File
• Postgresql.conf file contains parameters to help configure and
manage performance of the database server.
PG_setting TABLE:
• It does not make any change in main config file postgresql.conf but it
changes postgresql.auto.conf. When we restart or reload the conf ,
the configuration applied as in postgresql.conf if same parameter is
not avilable in postgresql.auto.conf.
pg_ident.conf file:
• User name map can be applied to map the operating system user
name to a database user.
Sample :
# MAP IDENT POSTGRESQL_USERNAME
The file shown in allows either of the system users rmartin or jpenny to
connect as the PostgreSQL sales user, and allows the system user named
auditor to connect to PostgreSQL as either sales, or postgres.
pg_hba.conf File :
# replication privilege.
TYPE
Host: is used to specify remote hosts that are allowed to connect to the
PostgreSQL server. PostgreSQL's postmaster backend must be running
with the -i option (TCP/IP) in order for a host entry to work correctly.
Local : is semantically the same as a host entry. However, you do not need
to specify a host that is allowed to connect. The local entry is used for
DATABASE
This is the database name that the specified host is allowed to connect to.
The database keyword has three possible values:
All : keyword specifies that the client connecting can connect to any
database the PostgreSQL server is hosting.
Same user : keyword specifies that the client can only connect to a
database that matches the clients authenticated user name.
IP ADDR/NET MASK
AUTHENTICATION
Crypt : This method is similar to the password method. When using crypt,
the password is not sent in clear text, but through a simple form of
encryption. The use of this method is not very secure, but is better than
using the clear text password method.
Ident : This method specifies that an ident map should be used when a
host is requesting connections from a valid IP address listed in the
pg_hba.conf file. This method requires one option.
The required option may be either the special term sameuser, or a named
map that is defined within the pg_ident.conf file.
Module Objective:
Example :
from psql prompt: create database siddhu owner postgres;
With createdb utility on OS command prompt :
$ createdb siddhu -O postgres
Example :
User in PostgreSQL:
PostgreSQL Administration (Windows & Linux) 39
• Db users and Operating users are completely separate.
• Users name should be unique and should not start with pg_.
• Only super users or users with create role privilege can create a
user.
Shall the new role be allowed to create more new roles? (y/n) y
“--Interactive option will ask the required parameter while creating user.”
This will create the super user. We can check users details by meta
command
\du.
$ Createuser –-interactive
Example :
Assign the user privileges to another user before dropping the user.
Example :
Privileges in PostgreSQL:
• There are two types of privileges – Cluster level and Object level
Grant Examples:
Revoke Examples:
• Create Schema
• Create Schema for a user, the schema will also be named as the user
• Drop a Schema
NOTE:: We cannot drop schema if there are any object associate with
it.
Example :
search_path
-----------------
"$user", public
( 1 row)
The session_user is normally the user who initiated the current database
connection; but superusers can change this setting with SET SESSION
AUTHORIZATION. Both are same.
Example :
Test1=# \dt
List of relations
--------+---------+-------+----------
(1 rows)
Database level setting : alter database mydb set search_path="$user",
public;
User Level Setting : alter role johnny set search_path = "$user", public;
Option #1 (graceful):
SELECT pg_cancel_backend(<PID>);
Option #2 (forceful):
SELECT pg_terminate_backend(<PID>);
Query to find high cpu usage and which query is causing it.
You can also use pg_activity utility to monitor the cpu usage.
We'll create two database tables that will allow you to query CPU and
memory usage from within the database connection. This way your
applications can monitor the health of the servers without needing to worry
about another connection or another protocol.
You can run these commands on the master database and they will
propagate to all the slave databases as well.
First, load the file foreign data wrapper and create the foreign data server:
Creating the table that will let you query memory info is similar:
or
with foo as (
SELECT
schemaname, tablename, hdr, ma, bs,
SUM((1-null_frac)*avg_width) AS datawidth,
MAX(null_frac) AS maxfracsum,
hdr+(
SELECT 1+COUNT(*)/8
FROM pg_stats s2
WHERE null_frac<>0 AND s2.schemaname = s.schemaname AND
s2.tablename = s.tablename
PostgreSQL Administration (Windows & Linux) 52
) AS nullhdr
FROM pg_stats s, (
SELECT
(SELECT current_setting('block_size')::NUMERIC) AS bs,
CASE WHEN SUBSTRING(v,12,3) IN ('8.0','8.1','8.2') THEN 27
ELSE 23 END AS hdr,
CASE WHEN v ~ 'mingw32' THEN 8 ELSE 4 END AS ma
FROM (SELECT version() AS v) AS foo
) AS constants
GROUP BY 1,2,3,4,5
), rs as (
SELECT
ma,bs,schemaname,tablename,
(datawidth+(hdr+ma-(CASE WHEN hdr%ma=0 THEN ma ELSE hdr
%ma END)))::NUMERIC AS datahdr,
(maxfracsum*(nullhdr+ma-(CASE WHEN nullhdr%ma=0 THEN ma
ELSE nullhdr%ma END))) AS nullhdr2
FROM foo
), sml as (
SELECT
schemaname, tablename, cc.reltuples, cc.relpages, bs,
CEIL((cc.reltuples*((datahdr+ma-
(CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))
+nullhdr2+4))/(bs-20::FLOAT)) AS otta,
COALESCE(c2.relname,'?') AS iname, COALESCE(c2.reltuples,0) AS
ituples, COALESCE(c2.relpages,0) AS ipages,
COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::FLOAT)),0) AS
iotta -- very rough approximation, assumes all cols
FROM rs
JOIN pg_class cc ON cc.relname = rs.tablename
JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname
= rs.schemaname AND nn.nspname <> 'information_schema'
LEFT JOIN pg_index i ON indrelid = cc.oid
LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid
)
PSQL Commands:
Connect to Psql
It enables the users to query postgreSQL interactively and see the query
results.
postgres=# \c test1
postgres=# \l
postgres=# \ dt
Describe a table
postgres=# \d table_name
postgres=# \dn
postgres=# \df
postgres=# \dv
postgres=# \du
postgres=# \ds
postgres=# \g
Command history
postgres=# \s
postgres=# \s filename
postgres=# \?
postgres=# \timing
postgres=# \e
postgres=# \ef
postgres=# \a
postgres=# \H
Connection Information
postgres=# \conninfo
Quit psql
postgres=# \o <filename>
postgres=# \w filename
PostgreSQL SYSTEM_CATALOGS
The system catalogs are the place where a relational database management
system stores schema metadata, such as information about tables and
columns, and internal bookkeeping information. PostgreSQL's system
catalogs are regular tables.
Name Description
pg_database Stores general database info
pg_stat_database Contains stats information of
database
pg_tablespace Contains Tablespace information
pg_operator Contains all operator information
pg_available_extensio List all available extensions
ns
• Current User
postgres=# select current_user;
• Current Database
postgres=# select current_database();
Module Objectives:
• Table Inheritance
• Table Partitioning
• Copy Table
• A child table can have extra fields of its own in addition to the
inherited columns.
• Query references all rows of that master table plus all of its children
tables.
• “Only” keyword can be used to indicate that the query should apply
only to a particular table and not any tables.
• Any update or delete on parents table without only affects the records
in child table.
Example:
Create Table:
create table orders(orderno serial, flightname varchar(100),boarding
varchar(100),status varchar(100),source varchar(100));
Insert Records:
Update Parent:
nano=# rollback;
ROLLBACK
nano=# select * from orders;
orderno | flightname | boarding | status | source
---------+------------+----------+--------+-----------
1 | aircanada | xyz | ontime | employees
2 | nippon | chn | ontime | website
3 | luftansa | chn | ontime | app
5 | etihad | aud | ontime | agent001
6 | emirates | dxb | ontime | agent007
(5 rows)
Delete:
nano=# delete from orders;
DELETE 5
nano=# select * from orders;
orderno | flightname | boarding | status | source
---------+------------+----------+--------+--------
(0 rows)
Drop Table:
nano=# drop table orders;
ERROR: cannot drop table orders because other objects depend on it
DETAIL: table online_booking depends on table orders
table agent_booking depends on table orders
HINT: Use DROP ... CASCADE to drop the dependent objects too.
nano=# drop table orders cascade;
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to table online_booking
drop cascades to table agent_booking
DROP TABLE
Table Partitioning :
Example:
Create Index:
nano=# create index booking_jan_idx on jan_booking using
btree(booking_date);
CREATE INDEX
Create Function:
Create Trigger:
Insert Records:
Copy Table is used to copy the structure of a table along with data.
Unlike Inheritance table , copy table does not have any relationship with
the base table.
Example:
Create Table:
nano=# create table train_bookings(trainno serial,trainname
varchar(200),destination varchar(100));
Insert Records:
nano=# insert into train_bookings(trainname,destination)
values('express','toronto');
INSERT 0 1
nano=# insert into train_bookings(trainname,destination)
values('semiexpress','montreal');
INSERT 0 1
nano=# insert into train_bookings(trainname,destination)
values('goods','calgary');
INSERT 0 1
nano=# select * from train_bookings;
trainno | trainname | destination
---------+-------------+-------------
1 | express | toronto
nano=# \d train_bookings
Table "public.train_bookings"
Column | Type | Collation | Nullable | Default
-------------+------------------------+-----------+----------
+-------------------------------------------------
trainno | integer | | not null |
nextval('train_bookings_trainno_seq'::regclass)
trainname | character varying(200) | | |
destination | character varying(100) | | |
nano=# \d train_dest
Table "public.train_dest"
Column | Type | Collation | Nullable | Default
-------------+------------------------+-----------+----------+---------
trainno | integer | | |
trainname | character varying(200) | | |
destination | character varying(100) | | |
Drop Table:
Module Objective:
• Create tablespaces
• Drop tablespaces
• Temporary tablespaces
“Tablespace does not holds any data. Data is still located in the disk.
Tablespace just map a logical name for the physical location of the
data on the disk. It just a pointer to the location of the data.
Tablespace can be used to segregate the data i.e. data in drive a and
indexes in drive d. ”
• WAL files object on fast media and archive data on slow media.
• In Iinux , postgres user must have the permission to read write on the
folder.
DEFAULT TABLESPACE:
Drop tablespace
MOVE TABLE
BETWEEN
TABLE
SPACES:
• Move tables
from one
tablespace to
another
Syntax:
alter table
test1 set
tablespace
pg_default
• Temporary tablespace does not store any data and their no persistent
file left when we shutdown database.
• Backup is a copy of data taken from the database and can be used to
reconstruct in case of a failure.
Logical Backup:
• Logical Backups are simple and the textual representation of the data
in the databases.
Pg_dump :
We can use any standard compression utility to compress the dump like gz
( Linux only)
We can split the dumps into smaller chunks of desirable size for easy
maintenance.
Syntax :
pg_dump test1 | split -b 1k - /var/lib/pgsql/11/backups/test1backup
Compressed & split backup
$ pg_dump -h localhost -U postgres -W -d mydb | gzip | split -b 100m –
mydb.sql.gz
We can restore a single table from a full pg_dump file without restoring
the entire database.
Syntax:
Linux :
First we check the status that archive in ON or Off. Below command will
be used in psql.
#show archive_mode
returns On or Off.
2. archive_mode = on
archive_command is the most imp parameter which will copy the wal
files from one location to another safe location ie. Archive directory.
After the parameter is set , start the cluster psql # pg_ctl start.
Check the destination location if any files are there, if not we can do a test
by firing the below command in psql
#select pg_stop_backup();
• All wal segments would have been archived to form a complete set
of backup files.
However, archive files alone will not help us in restoring a database in case
of a failure.The core of any backup and restore strategy is full backup or
the base backup.Archive files work in conjunction with full backup in
order to restore a database until a certain time.
For example.
I have taken a full backup or a base backup on Sunday and my system
crashed somewhere on Monday 10 am.
In this section, we are going to learn how to take a full online backup.
The reason this type of backup is preferred because in real time, we cannot
afford to have a down time, the system availability is a huge criteria and
the expectation from the business is that the system should be available 24
by seven.
One is through a low level API, which is what we are going to discuss
now.
False - That I'll give the parameter false, which is to inform PG that it can
take its time for doing the IO and not return the control back to the user
immediately.
In above image we can see the permission denied error, actually this log
file is in use. When we stop the backup it will automatically copy to
archive folder.
You can specify the stop back up time and say that I want to recover my
database.
Now we have the complete online backup with the last wal files. If we
want to restore it we can untar the backup2.tar copy the wal file in folder
and start cluster.
Pg_basebackup:
• It automatically puts and take out the database from backup mode.
• Backups are always taken of the entire database cluster and cannot be
used for single database or objects.
But for a larger database. This is not possible because the backup me takes
hours to get completed.
On Monday, by the end of the day, end of business by five or five thirty, I
would go ahead and take a backup of all the archive files, which are
generated from my last backup to end up in this Monday.
then I flush everything out and Sunday we start the routine again.
-h : host
-U: user
-p : port
-D : destination folder
-z : zip
-P : show progress
-Ft : format tar.
-Xs: also archive the transaction which is happening during the
backup itself.
Example (postgresql.conf):
Psql # select
pg_current_wal_lsn(),pg_wal_file_name(pg_current_wal_lsn());
#output
• copy the whole old cluster data directory and any tablespaces to a
temporary location.
• Restore the database files from your file system backup or base
backup. (don’t move)
• Start the server (pg_ctl start) . The server will go into recovery mode
and proceed to read through the archived WAL files it needs.
Prerequisite:
Ensure Archive Mode is turned on and archiving is happening.
Example:
Step 1:
Create a table and insert few records, update or delete ( perform some
transaction which can be archived)
I have created a table named test1 and did few operations on it like insert
and update.
Currently my table has 5 rows.
Step 2:
Verify archive log folder whether all wal files are archived.
Step 4:
Take a pg_basebackup of the entire cluster. Using the below command.
This will generate 2 tar files
One is of the entire data and other one is wal files(pg_wal.tar)
$ pg_basebackup -Ft -D var/pgtmp – example syntax
Step 5:
Stop the cluster and delete the data folder( we are going to mimic a crash
here were we lost our data folder).
Step 6: Now we are going to restore the data folder using the backup
which we took.
First create data folder in the same location where we removed.
Second move in to the data folder and create pg_wal folder.
Let us start with the restore of data folder and wal files using the
pg_basebackup which we took.
You can see that the wal files are restored in the pg_wal folder.
Step 7: Now we need to ensure that the database is consistent and tell our
database server to copy files from our archived location to WAL file
location. For this we need to edit postgresql.conf file.
The cluster started successfully. Let us check whether the table test1 with 5
records exist or not.
PITR
Let us try now to a PITR.
Step 1: We will use the same table to perform PITR. I will be adding few
more row to the existing table to generate archives.
Now check the archive log folder whether we got any new archives.
Step 2:
Take a fresh pg_basebackup.
Step 3:
Now insert few more rows in the test1 table after that backup. Before my
row count was 10 now it is 15.
Step 4:
Now I will mimic a crash by deleting my data directory.
Step 5:
Restore the database from the backup which we took @ step 2.
Make sure we create the data and pg_wal folder before we start the restore.
Step 6:
I have to recover my database till the point of 10 records. So I will check
the archive log which was generated by that time.
Step 8:
Now start the cluster and it will recover the database till the specified time.
Ensure to
Change the permission on data folder to 700
Step 9:
Start the cluster
#cat /var/log/postgresql/postgresql-13-main.log
Note: if the database was ever shutdown uncleanly, all the stats are
reset. You could check pg_stat_database. Or they can be reset manually,
either for the database or for individual tables.
--#Database size
SELECT pg_size_pretty(pg_database_size('uidservices'));
SELECT datname as db_name,
pg_size_pretty(pg_database_size(datname)) as db_usage FROM
pg_database
order by 2 ;
SELECT t_xmin,
t_xmax,
tuple_data_split('adv_txn_log_012021'::regclass,
t_data,
t_infomask,
t_infomask2, t_bits) FROM
heap_page_items(get_raw_page('adv_txn_log_012021', 0));
select txid_current();
--Connect to the database and run the following query to list tables that are
currently processed by the autovacuum daemon:
SELECT
*,
relid :: regclass,
heap_blks_scanned / heap_blks_total :: float * 100 "% scanned",
heap_blks_vacuumed / heap_blks_total :: float * 100 "% vacuumed"
FROM
pg_stat_progress_vacuum;
-- #index usage
SELECT
t.schemaname,
t.tablename,
c.reltuples::bigint AS num_rows,
pg_size_pretty(pg_relation_size(c.oid)) AS table_size,
psai.indexrelname AS index_name,
pg_size_pretty(pg_relation_size(i.indexrelid)) AS index_size,
CASE WHEN i.indisunique THEN 'Y' ELSE 'N' END AS "unique",
psai.idx_scan AS number_of_scans,
psai.idx_tup_read AS tuples_read,
psai.idx_tup_fetch AS tuples_fetched
FROM
pg_tables t
LEFT JOIN pg_class c ON t.tablename = c.relname
LEFT JOIN pg_index i ON c.oid = i.indrelid
LEFT JOIN pg_stat_all_indexes psai ON i.indexrelid = psai.indexrelid
WHERE
t.schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY 1, 2;
ceil(reltuples/floor((bs-pageopqdata-pagehdr)/(4+nulldatahdrwidth)::float)
), 0 -- ItemIdData size + computed avg size of a tuple (nulldatahdrwidth)
) AS est_pages,
coalesce(1 +
ceil(reltuples/floor((bs-pageopqdata-pagehdr)*fillfactor/(100*(4+nulldatah
drwidth)::float))), 0
) AS est_pages_ff,
bs, nspname, tblname, idxname, relpages, fillfactor, is_na
-- , pgstatindex(idxoid) AS pst, index_tuple_hdr_bm, maxalign,
pagehdr, nulldatawidth, nulldatahdrwidth, reltuples -- (DEBUG INFO)
FROM (
SELECT maxalign, bs, nspname, tblname, idxname, reltuples,
relpages, idxoid, fillfactor,
( index_tuple_hdr_bm +
maxalign - CASE -- Add padding to the index tuple header to
align on MAXALIGN
WHEN index_tuple_hdr_bm%maxalign = 0 THEN maxalign
ELSE index_tuple_hdr_bm%maxalign
END
+ nulldatawidth + maxalign - CASE -- Add padding to the data to
align on MAXALIGN
WHEN nulldatawidth = 0 THEN 0
WHEN nulldatawidth::integer%maxalign = 0 THEN maxalign
ELSE nulldatawidth::integer%maxalign
END
)::numeric AS nulldatahdrwidth, pagehdr, pageopqdata, is_na
-- , index_tuple_hdr_bm, nulldatawidth -- (DEBUG INFO)
FROM (
SELECT n.nspname, ct.relname AS tblname, i.idxname, i.reltuples,
i.relpages,
i.idxoid, i.fillfactor, current_setting('block_size')::numeric AS bs,
CASE -- MAXALIGN: 4 on 32bits, 8 on 64bits (and mingw32 ?)
(2 rows)
see above to display all records from table tel_directory it will be going
thru sequential scan and take 0.00 initial cost and 82.00 actual cost.
Below is the example with filter applied.
as you see in above image after creating index the cost is reduced and path
is also change. So by this we can check whether index is using effectively
or not.
Data Fragmentation:
For the routine check we can use the Extension pgstattuple module.
The following sql shows table txn_log is heavily fragmented with 98.71 %
free space, and tuple percent is only 9%.
(1 row)
---------+------------+------------+---------------+----------------+------------+-------------+---------------+------------------
+--------------------
(1 row)
SELECT pg_size_pretty(pg_relation_size('txn_req_log_022022')) as
table_size, pg_size_pretty
(pg_relation_size('activity_req_log_pkey_txn_req_log_022022')) as
index_size, (pgstattuple ('txn_req_log_022022')).dead_tuple_percent;
select schemaname,
relname,
n_live_tup,
n_dead_tup,
last_autovacuum,
last_autoanalyze
from pg_stat_user_tables
Vacuum:
attname | format_type
----------+------------------------
tableoid | oid
cmax | cid
xmax | xid
cmin | cid
PostgreSQL Administration (Windows & Linux) 121
xmin | xid
ctid | tid
emp_id | integer
emp_name | character varying(100)
dept_id | integer
(9 rows)
tableoid : Contains the Object ID of the table that contains this row. Used
by queries that select from inheritance hierarchies.
xmin : The transaction ID(xid) of the inserting transaction for this row
version. Upon update, a new row version is inserted. Let’s see the
following log to understand the xmin more.
# select txid_current();
txid_current
--------------
646 – Remember this
(1 row)
As you see in the above log, the transaction ID was 646 for the command
=> select txid_current(). Thus, the immediate INSERT statement got a
transaction ID 647. Hence, the record was assigned an xmin of 647. This
means, no running transaction ID that has started before the ID 647, can
see this row. In other words, already running transactions with txid less
than 647 cannot see the row inserted by txid 647.
xmax : This values is 0 if it was not a deleted row version. Before the
DELETE is committed, the xmax of the row version changes to the ID of
the transaction that has issued the DELETE. Let’s observe the following
log to understand that better.
As you see in the above logs, the xmax value changed to the transaction
ID that has issued the delete. If you have issued a ROLLBACK, or if the
transaction got aborted, xmax remains at the transaction ID that tried to
DELETE it (which is 655) in this case.
when you check the count after DELETE, you would not see the records
that have been DELETED. To see any row versions that exist in the
table but are not visible, we have an extension called pageinspect. The
pageinspect module provides functions that allow you to inspect the
contents of database pages at a low level, which is useful for debugging
purposes. Let’s create this extension to see the older row versions those
have been deleted.
we could still see 10 records in the table even after deleting 5 records from
it. Also, you can observe here that t_xmax is set to the transaction ID that
has deleted them. These deleted records are retained in the same table to
serve any of the older transactions that are still accessing them.
cmax : The command identifier within the deleting transaction or zero. (As
per the documentation). However, both cmin and cmax are always the
same as per the PostgreSQL source code.
cmin : The command identifier within the inserting transaction. You could
see the cmin of the 3 insert statements starting with 0.
ctid : The physical location of the row version within its table. Note that
although the ctid can be used to locate the row version very quickly, a
row's ctid will change if it is updated or moved by VACUUM FULL.
Therefore ctid is useless as a long-term row identifier. A primary key
should be used to identify logical rows.
There is a utility or an option called vacuum that is provided in
postgreSQL.
Vacuum:
• VACUUM does an additional task. All the rows that are inserted
and successfully committed in the past are marked as frozen,
which indicates that they are visible to all the current and future
transactions.
Vacuum Full
• VACUUM FULL rewrites the entire contents of the table into a new
disk file with no extra space.
• Unused space to be returned to the operating system.
• Takes much longer than regular vacuum and places exclusive lock
the tables. We should do this activity in non business hours.
• full vacuum takes extra disk space, since it writes a new copy of
the table and doesn't release the old copy until the operation is
complete.
) lt;
\gexec
Run the following query to list tables that are currently processed by the
autovacuum daemon:
SELECT p.pid,
p.datname,
p.query,
p.backend_type,
a.phase,
a.heap_blks_scanned / a.heap_blks_total::float * 100 AS "% scanned",
a.heap_blks_vacuumed / a.heap_blks_total::float * 100 AS "%
vacuumed",
pg_size_pretty(pg_table_size(a.relid)) AS "table size",
pg_size_pretty(pg_indexes_size(a.relid)) AS "indexes size",
pg_get_userbyid(c.relowner) AS owner
FROM pg_stat_activity p
JOIN pg_stat_progress_vacuum a ON a.pid = p.pid
JOIN pg_class c ON c.oid = a.relid
WHERE p.query LIKE 'autovacuum%';
Output:
-[ RECORD 2 ]+-------------------------------------------
pid | 286964
datname | test_db
query | autovacuum: VACUUM public.my_table
backend_type | autovacuum worker
phase | vacuuming indexes
% scanned | 100
% vacuumed | 0
table size | XX
indexes size | XX
If there are multiple tables eligible for manual vacuuming, focus on the
largest ones first. The larger the table, the longer the autovacuum process
can take. Therefore, applying this procedure on the largest tables first can
produce the biggest gains.
Vacuum then :
SELECT
pg_cancel_backend(286964)
FROM
pg_stat_progress_vacuum
WHERE
relid = 'public.pgbench_accounts' :: regclass;
VACUUM (
TRUNCATE off, INDEX_CLEANUP false,
VERBOSE, FREEZE
) public.my_table;
After the vacuum completes, you can optionally reindex the table. Our
optimized VACUUM command contained the INDEX_CLEANUP false
clause, which skips the index optimization stage. Bypassing index
optimization doesn’t cause any immediate issues, but if you frequently
vacuum the same tables with INDEX_CLEANUP false, it can lead to
index bloat in the long term. You may want to REINDEX your table
periodically if index bloat becomes a problem.
You can obtain TXID information at table level to identify tables that still
need vacuuming. SQL for top 10 tables ordered by transaction ID
utilization.
PostgresQL stores this transaction information about each and every row
in the system. And this information is used to determine whether a row
will be visible or not to other transactions.
What happens after four billion transaction is that whatever rows you have
deleted in the past will be visible. Whatever updates you have done to
record the old value will be visible.
#select
datname,age(datfrozenxid),current_setting('autovacuum_freeze_max_age')
from pg_database order by 2 desc;
datname age current_setting
vbts 96 200000000
#select txid_current();
95117
$ /usr/lib/postgresql/13/bin/postgres --single -D
/var/lib/postgresql/13/main/base/
--config-file=/etc/postgresql/13/main/postgresql.conf
autovacuum_multixact_freeze_max_age = 100000000,
vacuum_freeze_min_age = 0
autovacuum_freeze_max_age = 100000000,
autovacuum_multixact_freeze_max_age = 100000000,
vacuum_freeze_min_age = 0
# SELECT
oid::regclass::text AS table,
age(relfrozenxid) AS xid_age,
mxid_age(relminmxid) AS mxid_age,
least(
(SELECT setting::int
FROM pg_settings
(SELECT setting::int
FROM pg_settings
) AS tx_before_wraparound_vacuum,
pg_size_pretty(pg_total_relation_size(oid)) AS size,
pg_stat_get_last_autovacuum_time(oid) AS last_autovacuum
FROM pg_class
WHERE relfrozenxid != 0
ORDER BY tx_before_wraparound_vacuum;
PostgreSQL Administration (Windows & Linux) 136
Routine Reindexing:
• Reindex rebuilds an index using the data stored in index table and
eliminates empty spaces between pages
Cluster a Table:
When the data is being inserted into the table we can not restrict it to
be entered in particular order, so the data is collected across multiple
pages and these pages will be recalled when we search the data or
totaling the count because , it is not entered in a particular sequence
and it is scattered across pages. So cluster table is the option to
arrange the data physically on the disk according to index.
Created a table and insert data without ordering. Now we need to fetch the
data with order by clause to get sorted data. We created an index on ID.
• Workers check for inserts, update and deletes and execute vacuum
and analyze if needed.
What is Upgrade
• Minor releases never change the internal storage format and are
always compatible with earlier and later minor releases of the same
major version number.
• Security Fixes
• Enhanced Features
• End of Support
This is the faster upgrade utility provided for all kind of major and
minor upgrade.
Ensure all the application closed and all connections should be stopped
before backup to take consistent copy of backup.
it will ask the password for each database, if the database count is huge the
environment variable PGPASS can be set to avoid inputting the password
for each db.
2. After the successful backup stop the old cluster #pg_ctl -D <datafolder
path> stop.
7. Delete the “Create role postgres ..“ line from the dump. (Optional)
# psql -f /opt/bkpfolder/bkp1.sql
• pg_upgrade does its best to make sure the old and new clusters are
binary-compatible
Syntax:
Options:
- -b bindir
--old-bindir=bindir
-B bindir
--new-bindir=bindir
-c
--check
-d configdir
-D configdir
--new-datadir=configdir
-k
--link
Use hard links instead of copying files to the new cluster. This is the
fastest upgrade. Data directories remains in same location and creates a
link between new cluster and old data dirs. The drawback is we can’t go
back to old version.
--clone (Default)
Use efficient file cloning instead of copying files to the new cluster.
can go back to old version because links will not reset, but sufficient disk
space is required to hold both old and new copies.
-?
--help
This test should pass without any error and should say clusters are
compatible. (Ensure that you are in the postgresql-10 bin folder when you
execute this command)
8 Ensure the application is down and no connections can be made to
PostgreSQL. If needed block connection from pg_hba.conf file.
9 Backup data again(Depending on the backup strategy being used to
backup existing PostgreSQL) as postgres user
pg_basebackup -D /var/lib/pgsql/10/backups
or
pg_dumpall > /var/lib/pgsql/10/backups/clusterall.sql
10 .[postgres@dv-pc-post bin]$ cd /usr/pgsql-10/bin
./ analyze_new_cluster.sh
Introduction to Postgresql-13:
• Incremental sorting
B-Tree Deduplication
Version 13:
Incremental Sorting
Incremental sorting, which accelerates sorting data when data that is sorted
from earlier parts of a query are already sorted.
Example: index on c1 and you need to sort dataset by c1, c2. Then
incremental sort can help you because it wouldn’t sort the whole dataset,
but sort individual groups whose have the same value of c1 instead. The
incremental sort is extremely helpful when you have a LIMIT clause.
See diff. Between version 12 and 13. cost is dramatically reduced for same
query in version 13.
Parallel Vacuum
Max_parallel_maintenance_workers , Min_parallel_index_scan_size
parameter governs parallel vacuum.
Backup manifests
A tool to verify that the content of a backup matches the given manifest.
pg_verifybackup expects to find also the WAL files from the start to the
end of the backup, which I deliberately did not include in the backup. I can
skip verification of the WAL files with the "-n” option:
#pg_verifybackup -n ~/backups/1588374735/
Trusted Extensions
Drop Database:
Right now, if I want to know how much data or how much changes are
written to WAL files in bytes we can use this feature.
SYSTEM VIEWES: