{"id":41105,"date":"2026-08-27T10:14:05","date_gmt":"2026-08-27T07:14:05","guid":{"rendered":"https:\/\/profelis.com.tr\/?p=41105"},"modified":"2026-08-27T10:24:20","modified_gmt":"2026-08-27T07:24:20","slug":"how-a-disaster-recovery-drill-can-turn-into-a-problem-silent-hang-during-postgresql-restore-bug-19490","status":"publish","type":"post","link":"https:\/\/profelis.com.tr\/en\/2026\/08\/27\/felaket-kurtarma-tatbikati-nasil-soruna-donusebilir-postgresql-restore-surecinde-sessiz-kilitlenme-bug-19490\/","title":{"rendered":"How Can a Disaster Recovery Drill Turn into a Problem? Silent Lockup During the PostgreSQL Restore Process (Bug #19490)"},"content":{"rendered":"<div data-elementor-type=\"wp-post\" data-elementor-id=\"41105\" class=\"elementor elementor-41105\" data-elementor-post-type=\"post\">\n\t\t\t\t<div class=\"elementor-element elementor-element-729f895 e-flex e-con-boxed e-con e-parent\" data-id=\"729f895\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;pix_scale_in&quot;:&quot;none&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e300142 elementor-widget elementor-widget-heading\" data-id=\"e300142\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">The Danger Waiting Silently: While Everything Seems Fine...<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f734b2a elementor-widget elementor-widget-text-editor\" data-id=\"f734b2a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p><span style=\"font-weight: 400;\">For system administrators, disaster recovery (DR) tests are usually routine and predictable processes. At least, you might think so. You took a backup of your production environment and transferred it to your test server. The base backup opened without any issues, and everything looks fine. Now comes the turn of applying (replaying) the WAL (Write-Ahead Log) files, which will process the transactions that occurred after the backup into the database.<\/span><\/p><p><span style=\"font-weight: 400;\">You are monitoring the logs; WAL files are being pulled from the archive one by one, being processed\u2026 And then suddenly everything stops.<\/span><\/p><p><span style=\"font-weight: 400;\">At first, you might think that this is a large transaction block and the system is busy writing it to disk. Five minutes pass, ten minutes pass, it becomes half an hour\u2026 You look at the server's resource utilization; the CPU is idle, disk I\/O is almost zero. However, the recovery process does not end, and the database somehow fails to start up and give the \u201cdatabase system is ready to accept connections\u201d message. Gigabytes of WAL files waiting to be processed are lined up at the door, but no one inside is touching them. The most annoying part of it all is that the error logs are spotless. There is no crash, no error message; just silence and a frozen startup process.<\/span><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-23129a8 elementor-widget elementor-widget-image\" data-id=\"23129a8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"640\" height=\"360\" src=\"https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-2-1024x576.avif\" class=\"attachment-large size-large wp-image-41113\" alt=\"\" srcset=\"https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-2-1024x576.avif 1024w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-2-300x169.avif 300w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-2-768x432.avif 768w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-2-1536x864.avif 1536w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-2-18x10.avif 18w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-2.avif 1672w\" sizes=\"(max-width: 640px) 100vw, 640px\" title=\"\">\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-96eb8aa elementor-widget elementor-widget-heading\" data-id=\"96eb8aa\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">The Real Problem Itself: MultiXactOffsetSLRU<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a97df51 elementor-widget elementor-widget-text-editor\" data-id=\"a97df51\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p class=\"translation-block\"><span style=\"font-weight: 400\">Since the logs are not telling you anything, the next step is to investigate at the operating system level. When you examine what the stalled PostgreSQL startup process (PID) is waiting for, you may encounter the following situation: the process has entered a <\/span><span style=\"font-weight: 400;color: #ff6600\">futex_wait<\/span><span style=\"font-weight: 400\"> state, indicating a lock wait at the operating system level. When examined using PostgreSQL\u2019s internal monitoring tools\u2014or through <span style=\"color: #ff6600\">pg_stat_activity<\/span> if hot standby is enabled\u2014you can see the wait event where the process is stuck:<\/span><\/p><p><span style=\"color: #ff6600;\"><b>LWLock: MultiXactOffsetSLRU<\/b><\/span><\/p><p><span style=\"font-weight: 400;\">The system requested a lock for a MultiXact operation, but this lock has deadlocked in an infinite loop. Data cannot be read, written, and naturally the remaining WAL files cannot be processed.<\/span><\/p><p class=\"translation-block\"><span style=\"font-weight: 400\">While investigating the root cause, you may come across <\/span><span style=\"color: #ff6600\"><b>Bug #19490<\/b><\/span><span style=\"font-weight: 400\"> in the PostgreSQL community\u2019s bug reports (pgsql-bugs), describing this exact scenario.<\/span><\/p><p class=\"translation-block\"><span style=\"font-weight: 400\">So why did this lockup occur seemingly out of nowhere? The answer lies in an innocent-looking version difference. For example, while your production server may be running version <\/span><span style=\"color: #ff6600\"><b>16.8<\/b><\/span><span style=\"font-weight: 400\">, the backup server used for the restore test may be running version <\/span><span style=\"color: #ff6600\"><b>16.14<\/b><\/span><span style=\"font-weight: 400\"> because it was installed more recently. You might assume that a minor version difference is backward-compatible. <strong>However, a code change introduced to the <\/strong><\/span><strong>SimpleLruWriteAll() function in PostgreSQL 16.12 triggers this hidden deadlock during WAL replay across minor versions.<\/strong><\/p><p class=\"translation-block\"><span style=\"font-weight: 400\">If your WAL files suddenly stop being processed during a restore operation and the system freezes without any warning, <strong>you are not alone.<\/strong> Let\u2019s look at how to overcome this deadlock and bring the database back online.<\/span><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8511e58 elementor-widget elementor-widget-image\" data-id=\"8511e58\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"640\" height=\"360\" src=\"https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-3-1024x576.png\" class=\"attachment-large size-large wp-image-41109\" alt=\"\" srcset=\"https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-3-1024x576.png 1024w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-3-300x169.png 300w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-3-768x432.png 768w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-3-1536x864.png 1536w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-3-18x10.png 18w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-3.png 1672w\" sizes=\"(max-width: 640px) 100vw, 640px\" title=\"\">\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8a00ed7 elementor-widget elementor-widget-heading\" data-id=\"8a00ed7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Searching for a Temporary Solution: Downgrading<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8f981bf elementor-widget elementor-widget-text-editor\" data-id=\"8f981bf\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p><span style=\"font-weight: 400;\">After identifying the issue, the first thing that might come to mind is to bring the PostgreSQL version on the test server to the same level as production, that is, to 16.8 (or to 16.11, where the bug does not yet exist). It is theoretically possible to downgrade only the binary files without touching the data directory. However, dealing with downgrading packages and trying to resolve operating system dependencies is the last thing you would want to do. You need a much cleaner and more permanent solution.<\/span><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6778eb2 elementor-widget elementor-widget-heading\" data-id=\"6778eb2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Rescuing Process: PostgreSQL 16.15<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9935d50 elementor-widget elementor-widget-text-editor\" data-id=\"9935d50\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p class=\"translation-block\"><span style=\"font-weight: 400\">Fortunately, the PostgreSQL community identified Bug #19490 and addressed the issue. Released on <\/span><span style=\"color: #ff6600\"><b>August 13, 2026<\/b><\/span><span style=\"font-weight: 400\">, <\/span><span style=\"color: #ff6600\"><b>PostgreSQL 16.15<\/b><\/span><span style=\"font-weight: 400\"> provides a solution for systems affected by this problem. <strong>The release notes confirm that the deadlock involving SLRU locks during WAL replay has been resolved.<\/strong><\/span><\/p><p><span style=\"font-weight: 400;\">All you need to do is advance the server. Since this is a \u201cminor\u201d version update, you do not need to deal with database files or complex migration scenarios:<\/span><\/p><ol><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Stop the locked PostgreSQL service on the test server.<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\" class=\"translation-block\"><span style=\"font-weight: 400\">Use your operating system\u2019s package manager (apt, yum, etc.) to update the <\/span><span style=\"font-weight: 400\">postgresql-16<\/span><span style=\"font-weight: 400\"> package to version <\/span><span style=\"color: #ff6600\"><b>16.15<\/b><\/span><span style=\"font-weight: 400\">.<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Restart the service.<\/span><\/li><\/ol>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-bfc8406 elementor-widget elementor-widget-image\" data-id=\"bfc8406\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"640\" height=\"360\" src=\"https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-4-1024x576.png\" class=\"attachment-large size-large wp-image-41108\" alt=\"\" srcset=\"https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-4-1024x576.png 1024w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-4-300x169.png 300w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-4-768x432.png 768w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-4-1536x864.png 1536w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-4-18x10.png 18w, https:\/\/profelis.com.tr\/wp-content\/uploads\/2026\/08\/postgresql-kilitlenme-blog-4.png 1672w\" sizes=\"(max-width: 640px) 100vw, 640px\" title=\"\">\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-948abd0 elementor-widget elementor-widget-heading\" data-id=\"948abd0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Breaking of the Silence and Happy Ending<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-562c5e9 elementor-widget elementor-widget-text-editor\" data-id=\"562c5e9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p class=\"translation-block\"><span style=\"font-weight: 400\">After starting the PostgreSQL service, monitor the log file. Then the moment of resolution will arrive: gigabytes of WAL files that have remained untouched for hours will begin processing within seconds. <\/span><span style=\"font-weight: 400;color: #ff6600\">pg_stat_slru<\/span><span style=\"font-weight: 400\"> will reset, and the wait events will return to normal. There will be no deadlock or stalling. Within just a few minutes, you will see the expected line in the log file:<\/span><\/p><p><span style=\"font-weight: 400; color: #ff6600;\">LOG: database system is ready to accept connections<\/span><\/p><p><span style=\"font-weight: 400;\">Your database will start up healthily, full data consistency will be ensured, and your stressfully started restore test will conclude successfully.<\/span><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2689df7 elementor-widget elementor-widget-heading\" data-id=\"2689df7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Lessons to be Learned (Best Practices)<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5640eb7 elementor-widget elementor-widget-text-editor\" data-id=\"5640eb7\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p><span style=\"font-weight: 400;\">These kinds of restore tests serve as a reminder of a few golden rules regarding database management:<\/span><\/p><ol><li style=\"font-weight: 400;\" aria-level=\"1\" class=\"translation-block\"><b>Do Not Underestimate Minor Releases:<\/b> <i><span style=\"font-weight: 400\">Do not assume that \u201c16.x and 16.y are essentially the same.\u201d<\/span><\/i><span style=\"font-weight: 400\"> In the database world, small code changes can have major and unpredictable effects, especially in low-level core mechanisms such as WAL replay and SLRU.<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\" class=\"translation-block\"><b>Version Synchronization Is Essential:<\/b><span style=\"font-weight: 400\"> Ensure that servers used for restore testing or maintained for Disaster Recovery (DR) run <\/span><b>the exact same minor version<\/b><span style=\"font-weight: 400\"> as your production servers.<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\" class=\"translation-block\"><b>Stay Up to Date:<\/b><span style=\"font-weight: 400\"> If a version difference is unavoidable or you are setting up a new server, always use the latest stable release announced by the PostgreSQL community\u2014in this case, version 16.15.<\/span><\/li><\/ol><p class=\"translation-block\"><span style=\"font-weight: 400\">If your restore process freezes for no apparent reason and the logs provide no clues, a <span style=\"color: #ff6600\">silently waiting <\/span><\/span><span style=\"font-weight: 400;color: #ff6600\">MultiXactOffsetSLRU<\/span><span style=\"font-weight: 400\"><span style=\"color: #ff6600\"> lock<\/span> may be lurking in the background. The solution is within reach: <\/span><span style=\"color: #ff6600\"><b>update your server to version 16.15<\/b><\/span><span style=\"font-weight: 400\">, then sit back and watch the logs flow.<\/span><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>Explore the cause of the silent lockup during the PostgreSQL restore process, Bug #19490, and the solution introduced in PostgreSQL 16.15, along with the technical details.<\/p>","protected":false},"author":16,"featured_media":41111,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[45,75,129],"tags":[60,50],"class_list":["post-41105","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-yazi","category-postgresql","category-veritabani","tag-postgresql","tag-veritabani"],"_links":{"self":[{"href":"https:\/\/profelis.com.tr\/en\/wp-json\/wp\/v2\/posts\/41105","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/profelis.com.tr\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/profelis.com.tr\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/profelis.com.tr\/en\/wp-json\/wp\/v2\/users\/16"}],"replies":[{"embeddable":true,"href":"https:\/\/profelis.com.tr\/en\/wp-json\/wp\/v2\/comments?post=41105"}],"version-history":[{"count":15,"href":"https:\/\/profelis.com.tr\/en\/wp-json\/wp\/v2\/posts\/41105\/revisions"}],"predecessor-version":[{"id":41127,"href":"https:\/\/profelis.com.tr\/en\/wp-json\/wp\/v2\/posts\/41105\/revisions\/41127"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/profelis.com.tr\/en\/wp-json\/wp\/v2\/media\/41111"}],"wp:attachment":[{"href":"https:\/\/profelis.com.tr\/en\/wp-json\/wp\/v2\/media?parent=41105"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/profelis.com.tr\/en\/wp-json\/wp\/v2\/categories?post=41105"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/profelis.com.tr\/en\/wp-json\/wp\/v2\/tags?post=41105"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}