{"id":42323,"date":"2026-01-08T10:31:26","date_gmt":"2026-01-08T09:31:26","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/?p=42323"},"modified":"2026-01-08T10:31:26","modified_gmt":"2026-01-08T09:31:26","slug":"postgresql-an-introduction-to-row-locking","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/postgresql-an-introduction-to-row-locking\/","title":{"rendered":"PostgreSQL: An introduction to row locking"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Sometimes it is necessary to troubleshoot locks in PostgreSQL to figure out what is going on in the system. While locks are important and necessary in a database system, too many locks can also be an issue, performance wise and resource consumption wise. There are several levels of locks, e.g. table level and row level locks. Depending on what kind of locks are causing an issue you need to take other actions to resolve it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;ll start with some basics and a very simple playground: One simple table containing one row:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [1,3]; title: ; notranslate\" title=\"\">\npostgres=# create table t (a int);\nCREATE TABLE\npostgres=# insert into t values (1);\nINSERT 0 1\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">One source of information about locking is <a href=\"https:\/\/www.postgresql.org\/docs\/current\/view-pg-locks.html\">pg_locks<\/a>. Do we already see something in this catalog view? Indeed we do:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [1]; title: ; notranslate\" title=\"\">\npostgres=# select locktype,database::regdatabase,relation::regclass,pid,mode,granted,waitstart from pg_locks;\n  locktype  | database | relation | pid  |      mode       | granted | waitstart \n------------+----------+----------+------+-----------------+---------+-----------\n relation   | postgres | pg_locks | 9119 | AccessShareLock | t       | \n virtualxid |          |          | 9119 | ExclusiveLock   | t       | \n(2 rows)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">What we see here is our own session (ignore the second row with &#8220;virtualxid&#8221; for now):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [1]; title: ; notranslate\" title=\"\">\npostgres=# select pg_backend_pid();\n pg_backend_pid \n----------------\n           9119\n(1 row)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The question is why? We only did a simple select, but even a select which does not modify the database needs locking because while we&#8217;re reading nobody else is allowed to modify the underlying objects. This is what &#8220;AccessShareLock&#8221; is about: Others can still read, but not change.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you do the same in a second session you might expect to see four rows in total, but:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [2]; title: ; notranslate\" title=\"\">\n-- session 2\npostgres=# select locktype,database::regdatabase,relation::regclass,pid,mode,granted,waitstart from pg_locks;\n  locktype  | database | relation | pid  |      mode       | granted | waitstart \n------------+----------+----------+------+-----------------+---------+-----------\n relation   | postgres | pg_locks | 9673 | AccessShareLock | t       | \n virtualxid |          |          | 9673 | ExclusiveLock   | t       | \n(2 rows)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Seems a bit surprising but pg_locks shows only locks from active processes and once the statement completes the process is not active anymore and the lock is gone.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So what we can do to exclude our own locks is this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [1]; title: ; notranslate\" title=\"\">\npostgres=# select locktype,database::regdatabase,relation::regclass,pid,mode,granted,waitstart from pg_locks where pid != pg_backend_pid();\n locktype | database | relation | pid | mode | granted | waitstart \n----------+----------+----------+-----+------+---------+-----------\n(0 rows)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">The story is a bit different if we do the same thing in a transaction in the first session and then query the view in the second session:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [2,4,10]; title: ; notranslate\" title=\"\">\n-- session 1\npostgres=# begin;\nBEGIN\npostgres=*# select locktype,database::regdatabase,relation::regclass,pid,mode,granted,waitstart from pg_locks where pid != pg_backend_pid();\n locktype | database | relation | pid | mode | granted | waitstart \n----------+----------+----------+-----+------+---------+-----------\n(0 rows)\n\n-- session 2\npostgres=# select locktype,database::regdatabase,relation::regclass,pid,mode,granted,waitstart from pg_locks where pid != pg_backend_pid();\n  locktype  | database | relation | pid  |      mode       | granted | waitstart \n------------+----------+----------+------+-----------------+---------+-----------\n relation   | postgres | pg_locks | 9119 | AccessShareLock | t       | \n virtualxid |          |          | 9119 | ExclusiveLock   | t       | \n(2 rows)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Because the first session is still active and the transaction is open, this session still holds the lock. Ending the transaction releases the lock:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [2,6]; title: ; notranslate\" title=\"\">\n-- session 1\npostgres=*# end;\nCOMMIT\n\n-- session 2\npostgres=# select locktype,database::regdatabase,relation::regclass,pid,mode,granted,waitstart from pg_locks where pid != pg_backend_pid();\n locktype | database | relation | pid | mode | granted | waitstart \n----------+----------+----------+-----+------+---------+-----------\n(0 rows)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Lets start doing something with our table in session two:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [2,4]; title: ; notranslate\" title=\"\">\n-- session 2\npostgres=# begin;\nBEGIN\npostgres=*# select * from t;\n a \n---\n 1\n(1 row)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">How does it look like in session one?<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [1]; title: ; notranslate\" title=\"\">\npostgres=# select locktype,database::regdatabase,relation::regclass,pid,mode,granted,waitstart from pg_locks where pid != pg_backend_pid();\n  locktype  | database | relation | pid  |      mode       | granted | waitstart \n------------+----------+----------+------+-----------------+---------+-----------\n relation   | postgres | t        | 9673 | AccessShareLock | t       | \n virtualxid |          |          | 9673 | ExclusiveLock   | t       | \n(2 rows)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">This is consistent to the results above. As the second session is reading from the table and the transaction is still open, the lock is still there, no surprise. Lets update the row in the still open transaction and then have a look again in session one:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [2,6]; title: ; notranslate\" title=\"\">\n-- session 2\npostgres=*# update t set a = 2 where a = 1;\nUPDATE 1\n\n-- session 1\npostgres=# select locktype,database::regdatabase,relation::regclass,pid,mode,granted,waitstart from pg_locks where pid != pg_backend_pid();\n   locktype    | database | relation | pid  |       mode       | granted | waitstart \n---------------+----------+----------+------+------------------+---------+-----------\n relation      | postgres | t        | 9673 | AccessShareLock  | t       | \n relation      | postgres | t        | 9673 | RowExclusiveLock | t       | \n virtualxid    |          |          | 9673 | ExclusiveLock    | t       | \n transactionid |          |          | 9673 | ExclusiveLock    | t       | \n(4 rows)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Now we got a &#8220;RowExclusiveLock&#8221; in addition and that means nobody else can do anything with the new row\/tuple we&#8217;ve just created. When someone else (third session) is trying to perform the same update this will block:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [2,4]; title: ; notranslate\" title=\"\">\n-- session 3\npostgres=# begin;\nBEGIN\npostgres=*# update t set a = 2 where a = 1;\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">&#8230; and the results in the first session look like this (I have added an order by and the &#8220;page&#8221; and &#8220;tuple&#8221; columns):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [2]; title: ; notranslate\" title=\"\">\n-- session 1\npostgres=# select locktype,database::regdatabase,relation::regclass,pid,mode,granted,waitstart,page,tuple from pg_locks where pid != pg_backend_pid() order by pid;\n   locktype    | database | relation | pid  |       mode       | granted |           waitstart           | page | tuple \n---------------+----------+----------+------+------------------+---------+-------------------------------+------+-------\n relation      | postgres | t        | 9673 | RowExclusiveLock | t       |                               |      |      \n virtualxid    |          |          | 9673 | ExclusiveLock    | t       |                               |      |      \n transactionid |          |          | 9673 | ExclusiveLock    | t       |                               |      |      \n relation      | postgres | t        | 9673 | AccessShareLock  | t       |                               |      |      \n tuple         | postgres | t        | 9691 | ExclusiveLock    | t       |                               |    0 |     1\n transactionid |          |          | 9691 | ExclusiveLock    | t       |                               |      |      \n relation      | postgres | t        | 9691 | RowExclusiveLock | t       |                               |      |      \n virtualxid    |          |          | 9691 | ExclusiveLock    | t       |                               |      |      \n transactionid |          |          | 9691 | ShareLock        | f       | 2026-01-08 09:14:00.330564+01 |      |      \n(9 rows)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">What we see now is, that the third session (pid=9691) is trying to get the lock but can&#8217;t and must wait (waitstart) for the second session to release the lock. We can also see that the row\/tuple in question is in block\/page 0 and the tuple\/row is the first one in that block. Once session two either commits or rollbacks the update in session three will proceed but there is nothing to update as there is no row which matches the where clause anymore.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [2,7,13]; title: ; notranslate\" title=\"\">\n-- session 2\npostgres=*# commit;\nCOMMIT\n\n-- session 3\nUPDATE 0\npostgres=*# select * from t;\n a \n---\n 2\n(1 row)\n\npostgres=*# end;\nCOMMIT\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">In session one we can verify that all locks are gone:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [1]; title: ; notranslate\" title=\"\">\npostgres=# select locktype,database::regdatabase,relation::regclass,pid,mode,granted,waitstart,page,tuple from pg_locks where pid != pg_backend_pid() order by pid;\n locktype | database | relation | pid | mode | granted | waitstart | page | tuple \n----------+----------+----------+-----+------+---------+-----------+------+-------\n(0 rows)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Another example with 5 rows in the table and two sessions update only the last row:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [2,4,8,10,14,16,19]; title: ; notranslate\" title=\"\">\n-- session 1\npostgres=# truncate t;\nTRUNCATE TABLE\npostgres=# insert into t values (1),(2),(3),(4),(5);\nINSERT 0 5\n\n-- session 2\npostgres=# begin;\nBEGIN\npostgres=*# update t set a = -1 where a = 5;\nUPDATE 1\n\n-- session 3\npostgres=# begin;\nBEGIN\npostgres=*# update t set a = -1 where a = 5;\n\n-- session 1\npostgres=# select locktype,database::regdatabase,relation::regclass,pid,mode,granted,waitstart,page,tuple from pg_locks where pid != pg_backend_pid() order by pid;\n   locktype    | database | relation | pid  |       mode       | granted |           waitstart           | page | tuple \n---------------+----------+----------+------+------------------+---------+-------------------------------+------+-------\n relation      | postgres | t        | 9673 | RowExclusiveLock | t       |                               |      |      \n virtualxid    |          |          | 9673 | ExclusiveLock    | t       |                               |      |      \n transactionid |          |          | 9673 | ExclusiveLock    | t       |                               |      |      \n virtualxid    |          |          | 9691 | ExclusiveLock    | t       |                               |      |      \n transactionid |          |          | 9691 | ShareLock        | f       | 2026-01-08 09:58:38.867534+01 |      |      \n tuple         | postgres | t        | 9691 | ExclusiveLock    | t       |                               |    0 |     5\n transactionid |          |          | 9691 | ExclusiveLock    | t       |                               |      |      \n relation      | postgres | t        | 9691 | RowExclusiveLock | t       |                               |      |      \n(8 rows)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Now it is row number 5 in block 0. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The rows with &#8220;transactionid&#8221; and &#8220;virtualxid&#8221; are about the transactions, details <a href=\"https:\/\/www.postgresql.org\/docs\/current\/transaction-id.html\">here<\/a>. Those values are also recorded in pg_locks:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [2]; title: ; notranslate\" title=\"\">\n-- session 1\npostgres=# select locktype,database::regdatabase,relation::regclass,pid,mode,granted,waitstart,page,tuple,transactionid,virtualxid from pg_locks where pid != pg_backend_pid() order by pid;\n   locktype    | database | relation | pid  |       mode       | granted |           waitstart           | page | tuple | transactionid | virtualxid \n---------------+----------+----------+------+------------------+---------+-------------------------------+------+-------+---------------+------------\n relation      | postgres | t        | 9673 | RowExclusiveLock | t       |                               |      |       |               | \n virtualxid    |          |          | 9673 | ExclusiveLock    | t       |                               |      |       |               | 24\/22\n transactionid |          |          | 9673 | ExclusiveLock    | t       |                               |      |       |           836 | \n virtualxid    |          |          | 9691 | ExclusiveLock    | t       |                               |      |       |               | 25\/18\n transactionid |          |          | 9691 | ShareLock        | f       | 2026-01-08 09:58:38.867534+01 |      |       |           836 | \n tuple         | postgres | t        | 9691 | ExclusiveLock    | t       |                               |    0 |     5 |               | \n transactionid |          |          | 9691 | ExclusiveLock    | t       |                               |      |       |           837 | \n relation      | postgres | t        | 9691 | RowExclusiveLock | t       |                               |      |       |               | \n\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">When there are only a few locks in the database this is an easy way to find out who is blocking whom but if you have hundreds of sessions and locks there is a more convenient way to check for blockers and waiters, and this is the function <a href=\"https:\/\/www.postgresql.org\/docs\/current\/functions-info.html\">pg_blocking_pids<\/a>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [2]; title: ; notranslate\" title=\"\">\n-- session 1\npostgres=# select pg_blocking_pids(9691);\n pg_blocking_pids \n------------------\n {9673}\n(1 row)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Another option to check more details in regards to row locking is the extension <a href=\"https:\/\/www.postgresql.org\/docs\/current\/pgrowlocks.html\">pgrowlocks<\/a>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; highlight: [2,4]; title: ; notranslate\" title=\"\">\n-- session 1\npostgres=# create extension pgrowlocks;\nCREATE EXTENSION\npostgres=# select * from t as a, pgrowlocks(&#039;t&#039;) as b where b.locked_row = a.ctid;\n a | locked_row | locker | multi | xids  |       modes       |  pids  \n---+------------+--------+-------+-------+-------------------+--------\n 5 | (0,5)      |    836 | f     | {836} | {&quot;No Key Update&quot;} | {9673}\n(1 row)\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">In the next post we&#8217;ll look more closely on transaction IDs and virtual transaction IDs when it comes to locking.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sometimes it is necessary to troubleshoot locks in PostgreSQL to figure out what is going on in the system. While locks are important and necessary in a database system, too many locks can also be an issue, performance wise and resource consumption wise. There are several levels of locks, e.g. table level and row level&hellip;&nbsp;<\/p>\n","protected":false},"author":28,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","neve_meta_reading_time":"","_themeisle_gutenberg_block_has_review":false,"footnotes":""},"categories":[4133],"tags":[],"class_list":["post-42323","post","type-post","status-publish","format-standard","hentry","category-database"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v28.4 (Yoast SEO v28.7) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>PostgreSQL: An introduction to row locking - dbi services | Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/postgresql-an-introduction-to-row-locking\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"PostgreSQL: An introduction to row locking\" \/>\n<meta property=\"og:description\" content=\"Sometimes it is necessary to troubleshoot locks in PostgreSQL to figure out what is going on in the system. While locks are important and necessary in a database system, too many locks can also be an issue, performance wise and resource consumption wise. There are several levels of locks, e.g. table level and row level&hellip;&nbsp;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/postgresql-an-introduction-to-row-locking\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi services | Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/dbiservices\/\" \/>\n<meta property=\"article:published_time\" content=\"2026-01-08T09:31:26+00:00\" \/>\n<meta name=\"author\" content=\"Open source Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@dbiservices\" \/>\n<meta name=\"twitter:site\" content=\"@dbiservices\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Open source Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-an-introduction-to-row-locking\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-an-introduction-to-row-locking\\\/\"},\"author\":{\"name\":\"Open source Team\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/0b4548362cac3eeff8b3eaf329e3530a\"},\"headline\":\"PostgreSQL: An introduction to row locking\",\"datePublished\":\"2026-01-08T09:31:26+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-an-introduction-to-row-locking\\\/\"},\"wordCount\":650,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#organization\"},\"articleSection\":[\"Database\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-an-introduction-to-row-locking\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-an-introduction-to-row-locking\\\/\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-an-introduction-to-row-locking\\\/\",\"name\":\"PostgreSQL: An introduction to row locking - dbi services | Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-01-08T09:31:26+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-an-introduction-to-row-locking\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-an-introduction-to-row-locking\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/postgresql-an-introduction-to-row-locking\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"PostgreSQL: An introduction to row locking\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/\",\"name\":\"dbi services Blog\",\"description\":\"#BeSharing\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#organization\"},\"alternateName\":\"dbi Blog\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#organization\",\"name\":\"dbi services\",\"alternateName\":\"dbi\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/dbi-services-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/dbi-services-logo.png\",\"width\":512,\"height\":512,\"caption\":\"dbi services\"},\"image\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/dbiservices\\\/\",\"https:\\\/\\\/x.com\\\/dbiservices\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/dbi-services\\\/\",\"https:\\\/\\\/www.youtube.com\\\/user\\\/dbiservices\"],\"description\":\"Swiss IT consulting and services company specialised in efficient data infrastructures and platforms: databases, application servers, cloud, DevOps, digitalization, analytics, data quality and monitoring. Headquartered in Del\u00e9mont with offices in Nyon, Basel, Bern and Zurich.\",\"email\":\"info@dbi-services.com\",\"telephone\":\"+41 32 422 96 00\",\"legalName\":\"dbi services SA\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/0b4548362cac3eeff8b3eaf329e3530a\",\"name\":\"Open source Team\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/05\\\/open-source-author.png\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/05\\\/open-source-author.png\",\"contentUrl\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/05\\\/open-source-author.png\",\"caption\":\"Open source Team\"},\"description\":\"Posts published under the Open source Team account are collective contributions by the dbi services open infrastructure consultants. The practice covers open-source databases and platforms, PostgreSQL first of all, along with MySQL, MariaDB, and Linux, from architecture, replication, and high availability to performance tuning and operations under service level agreements, and contributes actively to the PostgreSQL community.\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/author\\\/open-source-team\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"PostgreSQL: An introduction to row locking - dbi services | Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/postgresql-an-introduction-to-row-locking\/","og_locale":"en_US","og_type":"article","og_title":"PostgreSQL: An introduction to row locking","og_description":"Sometimes it is necessary to troubleshoot locks in PostgreSQL to figure out what is going on in the system. While locks are important and necessary in a database system, too many locks can also be an issue, performance wise and resource consumption wise. There are several levels of locks, e.g. table level and row level&hellip;&nbsp;","og_url":"https:\/\/www.dbi-services.com\/blog\/postgresql-an-introduction-to-row-locking\/","og_site_name":"dbi services | Blog","article_publisher":"https:\/\/www.facebook.com\/dbiservices\/","article_published_time":"2026-01-08T09:31:26+00:00","author":"Open source Team","twitter_card":"summary_large_image","twitter_creator":"@dbiservices","twitter_site":"@dbiservices","twitter_misc":{"Written by":"Open source Team","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-an-introduction-to-row-locking\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-an-introduction-to-row-locking\/"},"author":{"name":"Open source Team","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/0b4548362cac3eeff8b3eaf329e3530a"},"headline":"PostgreSQL: An introduction to row locking","datePublished":"2026-01-08T09:31:26+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-an-introduction-to-row-locking\/"},"wordCount":650,"commentCount":0,"publisher":{"@id":"https:\/\/www.dbi-services.com\/blog\/#organization"},"articleSection":["Database"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/postgresql-an-introduction-to-row-locking\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-an-introduction-to-row-locking\/","url":"https:\/\/www.dbi-services.com\/blog\/postgresql-an-introduction-to-row-locking\/","name":"PostgreSQL: An introduction to row locking - dbi services | Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"datePublished":"2026-01-08T09:31:26+00:00","breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-an-introduction-to-row-locking\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/postgresql-an-introduction-to-row-locking\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/postgresql-an-introduction-to-row-locking\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"PostgreSQL: An introduction to row locking"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi services Blog","description":"#BeSharing","publisher":{"@id":"https:\/\/www.dbi-services.com\/blog\/#organization"},"alternateName":"dbi Blog","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.dbi-services.com\/blog\/#organization","name":"dbi services","alternateName":"dbi","url":"https:\/\/www.dbi-services.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/2026\/09\/dbi-services-logo.png","contentUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/2026\/09\/dbi-services-logo.png","width":512,"height":512,"caption":"dbi services"},"image":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/dbiservices\/","https:\/\/x.com\/dbiservices","https:\/\/www.linkedin.com\/company\/dbi-services\/","https:\/\/www.youtube.com\/user\/dbiservices"],"description":"Swiss IT consulting and services company specialised in efficient data infrastructures and platforms: databases, application servers, cloud, DevOps, digitalization, analytics, data quality and monitoring. Headquartered in Del\u00e9mont with offices in Nyon, Basel, Bern and Zurich.","email":"info@dbi-services.com","telephone":"+41 32 422 96 00","legalName":"dbi services SA"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/0b4548362cac3eeff8b3eaf329e3530a","name":"Open source Team","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/2022\/05\/open-source-author.png","url":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/2022\/05\/open-source-author.png","contentUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/2022\/05\/open-source-author.png","caption":"Open source Team"},"description":"Posts published under the Open source Team account are collective contributions by the dbi services open infrastructure consultants. The practice covers open-source databases and platforms, PostgreSQL first of all, along with MySQL, MariaDB, and Linux, from architecture, replication, and high availability to performance tuning and operations under service level agreements, and contributes actively to the PostgreSQL community.","url":"https:\/\/www.dbi-services.com\/blog\/author\/open-source-team\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/42323","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/28"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=42323"}],"version-history":[{"count":0,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/42323\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=42323"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=42323"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=42323"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}