Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Mastering PostgreSQL 15

You're reading from   Mastering PostgreSQL 15 Advanced techniques to build and manage scalable, reliable, and fault-tolerant database applications

Arrow left icon
Product type Paperback
Published in Jan 2023
Publisher Packt
ISBN-13 9781803248349
Length 522 pages
Edition 5th Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Hans-Jürgen Schönig Hans-Jürgen Schönig
Author Profile Icon Hans-Jürgen Schönig
Hans-Jürgen Schönig
Arrow right icon
View More author details
Toc

Table of Contents (16) Chapters Close

Preface 1. Chapter 1: PostgreSQL 15 Overview 2. Chapter 2: Understanding Transactions and Locking FREE CHAPTER 3. Chapter 3: Making Use of Indexes 4. Chapter 4: Handling Advanced SQL 5. Chapter 5: Log Files and System Statistics 6. Chapter 6: Optimizing Queries for Good Performance 7. Chapter 7: Writing Stored Procedures 8. Chapter 8: Managing PostgreSQL Security 9. Chapter 9: Handling Backup and Recovery 10. Chapter 10: Making Sense of Backups and Replication 11. Chapter 11: Deciding on Useful Extensions 12. Chapter 12: Troubleshooting PostgreSQL 13. Chapter 13: Migrating to PostgreSQL 14. Index 15. Other Books You May Enjoy

Observing deadlocks and similar issues

Deadlocks are an important issue and can happen in every database. Basically, a deadlock will happen if two transactions have to wait on each other.

In this section, you will see how this can happen. Let’s suppose we have a table containing two rows:

CREATE TABLE t_deadlock (id int);
INSERT INTO t_deadlock VALUES (1), (2);

The following example shows what can happen:

Transaction 1

Transaction 2

BEGIN;

BEGIN;

UPDATE t_deadlock

SET id = id * 10

WHERE id = 1;

UPDATE t_deadlock

SET id = id * 10

WHERE id = 2;

UPDATE t_deadlock

SET id = id * 10

WHERE id = 2;

Waiting on transaction 2

UPDATE t_deadlock

SET id = id * 10

WHERE id = 1;

Waiting on transaction 2

Waiting on transaction 1

Deadlock will be resolved after 1 second

(deadlock_timeout)

COMMIT;

ROLLBACK;

Table 2.10 – Understanding deadlocks

As soon as the deadlock is detected, the following error message will show up:

psql: ERROR: deadlock detected
DETAIL: Process 91521 waits for ShareLock on transaction 903;
   blocked by process 77185.
 Process 77185 waits for ShareLock on transaction 905;
 blocked by process 91521.
 HINT: See server log for query details.
 CONTEXT: while updating tuple (0,1) in relation "t_deadlock"

PostgreSQL is even kind enough to tell us which row has caused the conflict. In my example, the root of all evil is a tuple, (0, 1). What you can see here is ctid, which is a unique identifier of a row in a table. It tells us about the physical position of a row inside a table. In this example, it is the first row in the first block (0).

It is even possible to query this row if it is still visible in your transaction. Here’s how it works:

test=# SELECT ctid, * FROM t_deadlock WHERE ctid = '(0, 1)';
ctid   | id
-------+-----
(0,1)  |  10
 (1 row)

Keep in mind that this query might not return a row if it has already been deleted or modified.

However, this isn’t the only case where deadlocks can lead to potentially failing transactions. Transactions also cannot be serialized for various reasons. The following example shows what can happen. To make this example work, I assume that you’ve still got the two rows, id = 1 and id = 2:

Transaction 1

Transaction 2

BEGIN ISOLATION LEVEL REPEATABLE READ;

SELECT * FROM t_deadlock;

Two rows will be returned

DELETE FROM t_deadlock;

SELECT * FROM t_deadlock;

Two rows will be returned

DELETE FROM t_deadlock;

The transaction will error out

ROLLBACK; - we cannot COMMIT anymore

Table 2.11 – Transaction isolation and DELETE

In this example, two concurrent transactions are at work. As long as the first transaction is just selecting data, everything is fine because PostgreSQL can easily preserve the illusion of static data. But what happens if the second transaction commits a DELETE command? As long as there are only reads, there is still no problem. The trouble begins when the first transaction tries to delete or modify data that is already dead at this point. The only solution for PostgreSQL is to error out due to a conflict caused by our transactions:

test=# DELETE FROM t_deadlock;
psql: ERROR: could not serialize access due to concurrent update

Practically, this means that end users have to be prepared to handle erroneous transactions. If something goes wrong, properly written applications must be able to try again.

You have been reading a chapter from
Mastering PostgreSQL 15 - Fifth Edition
Published in: Jan 2023
Publisher: Packt
ISBN-13: 9781803248349
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime