{"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":"felaket-kurtarma-tatbikati-nasil-soruna-donusebilir-postgresql-restore-surecinde-sessiz-kilitlenme-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 Quietly Lurking Danger: When 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, processed... And then suddenly everything stops.<\/span><\/p><p><span style=\"font-weight: 400;\">At first, you might think 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 check the server's resource usage; the CPU is relaxed, disk I\/O is almost zero. However, the recovery process never ends, and the database just won't 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 outside, but no one inside is touching them. The most frustrating part of the job is that the error logs are spotless. There are no crashes, no error messages; 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><span style=\"font-weight: 400;\">Since the logs aren't telling you anything, let's drop down to the operating system level. When you examine what the hanging PostgreSQL startup process (PID) is waiting for, you might encounter this scenario: The process is a <\/span><span style=\"font-weight: 400; color: #ff6600;\">futex_wait<\/span><span style=\"font-weight: 400;\"> has entered the (OS-level deadlock) state. With PostgreSQL's own internal monitoring tools (or if hot standby is enabled <span style=\"color: #ff6600;\">pg_stat_activity<\/span> When you look through, you see the wait event it is stuck on:<\/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><span style=\"font-weight: 400;\">While investigating the root cause, if you browse through the PostgreSQL community error logs (pgsql-bugs), you will find exactly this scenario described <\/span><span style=\"color: #ff6600;\"><b>Bug #19490<\/b><\/span><span style=\"font-weight: 400;\"> You can face the truth.<\/span><\/p><p><span style=\"font-weight: 400;\">So why did this crash happen to you out of the blue? The answer is hidden in the seemingly innocent difference in \u201cversions.\u201d For example, your production server <\/span><span style=\"color: #ff6600;\"><b>16.8<\/b><\/span><span style=\"font-weight: 400;\"> when working on the version, because your backup server on which you performed the restore test is newly installed <\/span><span style=\"color: #ff6600;\"><b>16.14<\/b><\/span><span style=\"font-weight: 400;\"> version. You might think, \u201cAnyway, it's just a minor version difference, it is backward compatible.\u201d. <strong>However, in PostgreSQL 16.12 <\/strong><\/span><strong>The code change added to the SimpleLruWriteAll() function triggers this latent deadlock bug during WAL replay operations across minor versions.<\/strong><\/p><p><span style=\"font-weight: 400;\">If you also experience the issue where WAL files suddenly stop processing in the middle of a restore operation and the system silently hangs, <strong>You are not alone.<\/strong> Let's see how you can get out of this deadlock and get the database running.<\/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 package downgrades 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\">Rescuer 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><span style=\"font-weight: 400;\">Fortunately, the PostgreSQL community recognized this issue (Bug #19490) and took action. <\/span><span style=\"color: #ff6600;\"><b>August 13, 2026<\/b><\/span><span style=\"font-weight: 400;\"> published on the date of <\/span><span style=\"color: #ff6600;\"><b>PostgreSQL 16.15<\/b><\/span><span style=\"font-weight: 400;\"> its version has become the solution for those suffering precisely from this problem. <strong>Reviewing the release notes, it is seen that the deadlock on SLRU locks during WAL replay has been resolved.<\/strong><\/span><\/p><p><span style=\"font-weight: 400;\">All you need to do is move the server forward. 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\"><span style=\"font-weight: 400;\">via your operating system's package manager (apt\/yum etc.) <\/span><span style=\"font-weight: 400;\">postgresql-16<\/span><span style=\"font-weight: 400;\"> by updating your package <\/span><span style=\"color: #ff6600;\"><b>16.15<\/b><\/span><span style=\"font-weight: 400;\"> Downgrade to version.<\/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 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><span style=\"font-weight: 400;\">After starting the PostgreSQL service, observe the log file. And that moment of resolution will come\u2026 Gigabytes of WAL files, waiting untouched for hours, will begin to be processed in seconds. <\/span><span style=\"font-weight: 400; color: #ff6600;\">pg_stat_slru<\/span><span style=\"font-weight: 400;\"> It will be reset and wait events will return completely to normal. There will be no deadlocks and no hanging. 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\"><b>Don't Underestimate Minor Versions:<\/b> <i><span style=\"font-weight: 400;\">\u201c16.x and 16.y are the same anyway\u201d<\/span><\/i><span style=\"font-weight: 400;\"> Do not say that. In the database world, small code changes can lead to unpredictably large effects, especially in low-level kernel mechanisms like WAL replay and SLRU.<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><b>Version Synchronization is Required:<\/b><span style=\"font-weight: 400;\"> Compare the versions of the servers where you perform restore tests or keep as Disaster Recovery (DR) with your production servers. <\/span><b>on the exact same minor version<\/b><span style=\"font-weight: 400;\"> Make sure to keep holding it.<\/span><\/li><li style=\"font-weight: 400;\" aria-level=\"1\"><b>Stay Up to Date:<\/b><span style=\"font-weight: 400;\"> If version differences are inevitable or you are setting up a brand new server, always upgrade to the latest known stable version announced by the PostgreSQL community (in our case, 16.15).<\/span><\/li><\/ol><p><span style=\"font-weight: 400;\">If your restore process is freezing for no reason and the logs aren't telling you anything, maybe in the background <span style=\"color: #ff6600;\">waiting quietly and silently <\/span><\/span><span style=\"font-weight: 400; color: #ff6600;\">MultiXactOffsetSLRU<\/span><span style=\"font-weight: 400;\"><span style=\"color: #ff6600;\"> the lock<\/span> exists. The solution is not very far away; your server <\/span><span style=\"color: #ff6600;\"><b>Update to 16.15<\/b><\/span><span style=\"font-weight: 400;\"> and 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}]}}