Мой ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΎΠΏΡ‹Ρ‚ восстановлСния Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Postgres послС сбоя (invalid page in block 4123007 of relatton base/16490)

Π₯ΠΎΡ‡Ρƒ ΠΏΠΎΠ΄Π΅Π»ΠΈΡ‚ΡŒΡΡ с Π²Π°ΠΌΠΈ ΠΌΠΎΠΈΠΌ ΠΏΠ΅Ρ€Π²Ρ‹ΠΌ ΡƒΡΠΏΠ΅ΡˆΠ½Ρ‹ΠΌ ΠΎΠΏΡ‹Ρ‚ΠΎΠΌ восстановлСния ΠΏΠΎΠ»Π½ΠΎΠΉ работоспособности Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Postgres. Π‘ Π‘Π£Π‘Π” Postgres я познакомился ΠΏΠΎΠ» Π³ΠΎΠ΄Π° Π½Π°Π·Π°Π΄, Π΄ΠΎ этого ΠΎΠΏΡ‹Ρ‚Π° администрирования Π±Π°Π· Π΄Π°Π½Π½Ρ‹Ρ… Ρƒ мСня Π½Π΅ Π±Ρ‹Π»ΠΎ совсСм.

Мой ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΎΠΏΡ‹Ρ‚ восстановлСния Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Postgres послС сбоя (invalid page in block 4123007 of relatton base/16490)

Π― Ρ€Π°Π±ΠΎΡ‚Π°ΡŽ ΠΏΠΎΠ»Ρƒ-DevOps ΠΈΠ½ΠΆΠ΅Π½Π΅Ρ€ΠΎΠΌ Π² ΠΊΡ€ΡƒΠΏΠ½ΠΎΠΉ IT-ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ. Наша компания занимаСтся Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ³ΠΎ обСспСчСния для высоконагруТСнных сСрвисов, я ΠΆΠ΅ ΠΎΡ‚Π²Π΅Ρ‡Π°ΡŽ Π·Π° Ρ€Π°Π±ΠΎΡ‚ΠΎΡΠΏΠΎΡΠΎΠ±Π½ΠΎΡΡ‚ΡŒ, сопровоТдСниС ΠΈ Π΄Π΅ΠΏΠ»ΠΎΠΉ. ΠŸΠ΅Ρ€Π΅Π΄ΠΎ ΠΌΠ½ΠΎΠΉ поставили ΡΡ‚Π°Π½Π΄Π°Ρ€Ρ‚Π½ΡƒΡŽ Π·Π°Π΄Π°Ρ‡Ρƒ: ΠΎΠ±Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π½Π° ΠΎΠ΄Π½ΠΎΠΌ сСрвСрС. ΠŸΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ написано Π½Π° Django, Π²ΠΎ врСмя обновлСния Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ (ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ структуры Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ…), ΠΈ ΠΏΠ΅Ρ€Π΅Π΄ этим процСссом ΠΌΡ‹ снимаСм ΠΏΠΎΠ»Π½Ρ‹ΠΉ Π΄Π°ΠΌΠΏ Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Ρ‡Π΅Ρ€Π΅Π· ΡΡ‚Π°Π½Π΄Π°Ρ€Ρ‚Π½ΡƒΡŽ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ pg_dump Π½Π° всякий случай.

Π’ΠΎ врСмя снятия Π΄Π°ΠΌΠΏΠ° Π²ΠΎΠ·Π½ΠΈΠΊΠ»Π° нСпрСдвидСнная ошибка (вСрсия Postgres – 9.5):

pg_dump: Oumping the contents of table β€œws_log_smevlog” failed: PQgetResult() failed.
pg_dump: Error message from server: ERROR: invalid page in block 4123007 of relatton base/16490/21396989
pg_dump: The command was: COPY public.ws_log_smevlog [...]
pg_dunp: [parallel archtver] a worker process dled unexpectedly

Ошибка Β«invalid page in blockΒ» Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ ΠΎ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°Ρ… Π½Π° ΡƒΡ€ΠΎΠ²Π½Π΅ Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠΉ систСмы, Ρ‡Ρ‚ΠΎ ΠΎΡ‡Π΅Π½ΡŒ Π½Π΅Ρ…ΠΎΡ€ΠΎΡˆΠΎ. На Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… Ρ„ΠΎΡ€ΡƒΠΌΠ°Ρ… ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π»ΠΈ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ FULL VACUUM с ΠΎΠΏΡ†ΠΈΠ΅ΠΉ zero_damaged_pages для Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Π΄Π°Π½Π½ΠΎΠΉ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹. Π§Ρ‚ΠΎ ΠΆΠ΅, попрробСум…

ΠŸΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΊΠ° ΠΊ Π²ΠΎΡΡΡ‚Π°Π½ΠΎΠ²Π»Π΅Π½ΠΈΡŽ

Π’ΠΠ˜ΠœΠΠΠ˜Π•! ΠžΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ сдСлайтС Ρ€Π΅Π·Π΅Ρ€Π²Π½ΡƒΡŽ копию Postgres ΠΏΠ΅Ρ€Π΅Π΄ любой ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠΎΠΉ Π²ΠΎΡΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π±Π°Π·Ρƒ Π΄Π°Π½Π½Ρ‹Ρ…. Если Ρƒ вас Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Π°Ρ машина, остановитС Π±Π°Π·Ρƒ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ сдСлайтС ΡΠ½Π΅ΠΏΡˆΠΎΡ‚. Если Π½Π΅Ρ‚ возмоТности ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΡΠ½Π΅ΠΏΡˆΠΎΡ‚, остановитС Π±Π°Π·Ρƒ ΠΈ скопируйтС содСрТимоС ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³Π° Postgres (Π²ΠΊΠ»ΡŽΡ‡Π°Ρ wal-Ρ„Π°ΠΉΠ»Ρ‹) Π² Π½Π°Π΄Ρ‘ΠΆΠ½ΠΎΠ΅ мСсто. Π“Π»Π°Π²Π½ΠΎΠ΅ Π² нашСм Π΄Π΅Π»Π΅ – Π½Π΅ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Ρ…ΡƒΠΆΠ΅. ΠŸΡ€ΠΎΡ‡Ρ‚ΠΈΡ‚Π΅ это.

ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π² Ρ†Π΅Π»ΠΎΠΌ Π±Π°Π·Π° Ρƒ мСня Ρ€Π°Π±ΠΎΡ‚Π°Π»Π°, я ограничился ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΌ Π΄Π°ΠΌΠΏΠΎΠΌ Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ…, Π½ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΠ» Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ с ΠΏΠΎΠ²Ρ€Π΅ΠΆΠ΄Ρ‘Π½Π½Ρ‹ΠΌΠΈ Π΄Π°Π½Π½Ρ‹ΠΌΠΈ (опция -T, —exclude-table=TABLE Π² pg_dump).

Π‘Π΅Ρ€Π²Π΅Ρ€ Π±Ρ‹Π» физичСским, ΡΠ½ΡΡ‚ΡŒ ΡΠ½Π΅ΠΏΡˆΠΎΡ‚ Π±Ρ‹Π»ΠΎ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ. Π‘Π΅ΠΊΠ°ΠΏ снят, двигаСмся дальшС.

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠΉ систСмы

ΠŸΠ΅Ρ€Π΅Π΄ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠΎΠΉ восстановлСния Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡƒΠ±Π΅Π΄ΠΈΡ‚ΡŒΡΡ, Ρ‡Ρ‚ΠΎ Ρƒ нас всё Π² порядкС с самой Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠΉ систСмой. И Π² случаС ошибок ΠΈΡΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ ΠΈΡ…, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ…ΡƒΠΆΠ΅.

Π’ ΠΌΠΎΡ‘ΠΌ случаС файловая систСма с Π±Π°Π·ΠΎΠΉ Π΄Π°Π½Π½Ρ‹Ρ… Π±Ρ‹Π»Π° ΠΏΡ€ΠΈΠΌΠΎΠ½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π° Π² Β«/srvΒ» ΠΈ Ρ‚ΠΈΠΏ Π±Ρ‹Π» ext4.

ΠžΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ Π±Π°Π·Ρƒ Π΄Π°Π½Π½Ρ‹Ρ…: systemctl stop [email protected] ΠΈ провСряСм, Ρ‡Ρ‚ΠΎ файловая систСма Π½ΠΈΠΊΠ΅ΠΌ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΈ Π΅Ρ‘ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡ‚ΠΌΠΎΠ½Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ lsof:
lsof +D /srv

МнС ΠΏΡ€ΠΈΡˆΠ»ΠΎΡΡŒ Π΅Ρ‰Ρ‘ ΠΎΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π±Π°Π·Ρƒ Π΄Π°Π½Π½Ρ‹Ρ… redis, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΎΠ½Π° Ρ‚ΠΎΠΆΠ΅ исползовала «/srv». Π”Π°Π»Π΅Π΅ я ΠΎΡ‚ΠΌΠΎΠ½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π» /srv (umount).

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠΉ систСмы Π±Ρ‹Π»Π° Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½Π° с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ e2fsck с ΠΊΠ»ΡŽΡ‡ΠΈΠΊΠΎΠΌ -f (Force checking even if filesystem is marked clean):

Мой ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΎΠΏΡ‹Ρ‚ восстановлСния Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Postgres послС сбоя (invalid page in block 4123007 of relatton base/16490)

Π”Π°Π»Π΅Π΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹ dumpe2fs (sudo dumpe2fs /dev/mapper/gu2—sys-srv | grep checked) ΠΌΠΎΠΆΠ½ΠΎ ΡƒΠ±Π΅Π΄ΠΈΡ‚ΡŒΡΡ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π±Ρ‹Π»Π° ΠΏΡ€ΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½Π°:

Мой ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΎΠΏΡ‹Ρ‚ восстановлСния Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Postgres послС сбоя (invalid page in block 4123007 of relatton base/16490)

e2fsck Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ Π½Π° ΡƒΡ€ΠΎΠ²Π½Π΅ Ρ„Π°ΠΉΠ»ΠΎΠ²ΠΎΠΉ систСмы ext4 Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½ΠΎ, Π° это Π·Π½Π°Ρ‡ΠΈΡ‚, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Ρ‚ΡŒ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠΈ Π²ΠΎΡΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π±Π°Π·Ρƒ Π΄Π°Π½Π½Ρ‹Ρ…, Π° Ρ‚ΠΎΡ‡Π½Π΅Π΅ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒΡΡ ΠΊ vacuum full (само собой, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΡ€ΠΈΠΌΠΎΠ½Ρ‚ΠΈΡ€Π²ΠΎΠ°Ρ‚ΡŒ Ρ„Π°ΠΉΠ»ΠΎΠ²ΡƒΡŽ систСму ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ ΠΈ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Π±Π°Π·Ρƒ Π΄Π°Π½Π½Ρ‹Ρ…).

Если Ρƒ вас сСрвСр физичСский, Ρ‚ΠΎ ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΡŒΡ‚Π΅ состояниС дисков (Ρ‡Π΅Ρ€Π΅Π· smartctl -a /dev/XXX) Π»ΠΈΠ±ΠΎ RAID-ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π°, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ±Π΅Π΄ΠΈΡ‚ΡŒΡΡ, Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π½Π΅ Π½Π° Π°ΠΏΠΏΠ°Ρ€Π°Ρ‚Π½ΠΎΠΌ ΡƒΡ€ΠΎΠ²Π½Π΅. Π’ ΠΌΠΎΡ‘ΠΌ случаС RAID оказался Β«ΠΆΠ΅Π»Π΅Π·Π½Ρ‹ΠΉΒ», поэтому я попросил мСстного Π°Π΄ΠΌΠΈΠ½Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ состояниС RAID (сСрвСр Π±Ρ‹Π» Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… сотнях ΠΊΠΈΠ»ΠΎΠΌΠ΅Ρ‚Ρ€ΠΎΠ² ΠΎΡ‚ мСня). Он сказал, Ρ‡Ρ‚ΠΎ ошибок Π½Π΅Ρ‚, Π° это Π·Π½Π°Ρ‡ΠΈΡ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Ρ‚ΠΎΡ‡Π½ΠΎ ΠΌΠΎΠΆΠ΅ΠΌ Π½Π°Ρ‡Π°Ρ‚ΡŒ восстановлСниС.

ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° 1: zero_damaged_pages

ΠŸΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌΡΡ ΠΊ Π±Π°Π·Π΅ Ρ‡Π΅Ρ€Π΅Π· psql Π°ΠΊΠΊΠ°ΡƒΠ½Ρ‚ΠΎΠΌ, ΠΎΠ±Π»Π°Π΄Π°ΡŽΡ‰ΠΈΠΌ ΠΏΡ€Π°Π²Π°ΠΌΠΈ ΡΡƒΠΏΠ΅Ρ€ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ. Нам Π½ΡƒΠΆΠ΅Π½ ΠΈΠΌΠ΅Π½Π½ΠΎ ΡΡƒΠΏΠ΅Ρ€ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ, Ρ‚.ΠΊ. ΠΎΠΏΡ†ΠΈΡŽ zero_damaged_pages ΠΌΠΎΠΆΠ΅Ρ‚ ΠΌΠ΅Π½ΡΡ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ½. Π’ ΠΌΠΎΡ‘ΠΌ случаС это postgres:

psql -h 127.0.0.1 -U postgres -s [database_name]

ΠžΠΏΡ†ΠΈΡ zero_damaged_pages Π½ΡƒΠΆΠ½Π° для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ошибки чтСния (с сайта postgrespro):

ΠŸΡ€ΠΈ выявлСнии ΠΏΠΎΠ²Ρ€Π΅ΠΆΠ΄Ρ‘Π½Π½ΠΎΠ³ΠΎ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° страницы Postgres Pro ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ сообщаСт ΠΎΠ± ошибкС ΠΈ ΠΏΡ€Π΅Ρ€Ρ‹Π²Π°Π΅Ρ‚ Ρ‚Π΅ΠΊΡƒΡ‰ΡƒΡŽ Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΡŽ. Если ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ zero_damaged_pages Π²ΠΊΠ»ΡŽΡ‡Ρ‘Π½, вмСсто этого систСма Π²Ρ‹Π΄Π°Ρ‘Ρ‚ ΠΏΡ€Π΅Π΄ΡƒΠΏΡ€Π΅ΠΆΠ΄Π΅Π½ΠΈΠ΅, обнуляСт ΠΏΠΎΠ²Ρ€Π΅ΠΆΠ΄Ρ‘Π½Π½ΡƒΡŽ страницу Π² памяти ΠΈ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ. Π­Ρ‚ΠΎ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Ρ€Π°Π·Ρ€ΡƒΡˆΠ°Π΅Ρ‚ Π΄Π°Π½Π½Ρ‹Π΅, Π° ΠΈΠΌΠ΅Π½Π½ΠΎ всС строки Π² ΠΏΠΎΠ²Ρ€Π΅ΠΆΠ΄Ρ‘Π½Π½ΠΎΠΉ страницС.

Π’ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ ΠΎΠΏΡ†ΠΈΡŽ ΠΈ ΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ Π΄Π΅Π»Π°Ρ‚ΡŒ full vacuum Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹:

VACUUM FULL VERBOSE

Мой ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΎΠΏΡ‹Ρ‚ восстановлСния Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Postgres послС сбоя (invalid page in block 4123007 of relatton base/16490)
К соТалСнию, Π½Π΅ΡƒΠ΄Π°Ρ‡Π°.

ΠœΡ‹ ΡΡ‚ΠΎΠ»ΠΊΠ½ΡƒΠ»ΠΈΡΡŒ с Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎΠΉ ошибкой:

INFO: vacuuming "β€œpublic.ws_log_smevlog”
WARNING: invalid page in block 4123007 of relation base/16400/21396989; zeroing out page
ERROR: unexpected chunk number 573 (expected 565) for toast value 21648541 in pg_toast_106070

pg_toast – ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ хранСния Β«Π΄Π»ΠΈΠ½Π½Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ…Β» Π² Poetgres, Ссли ΠΎΠ½ΠΈ Π½Π΅ ΠΏΠΎΠΌΠ΅Ρ‰Π°ΡŽΡ‚ΡΡ Π² ΠΎΠ΄Π½Ρƒ страницу (ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ 8ΠΊΠ±).

ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° 2: reindex

ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ совСт ΠΈΠ· Π³ΡƒΠ³Π»Π° Π½Π΅ ΠΏΠΎΠΌΠΎΠ³. ПослС Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… ΠΌΠΈΠ½ΡƒΡ‚ поиска я Π½Π°ΡˆΡ‘Π» Π²Ρ‚ΠΎΡ€ΠΎΠΉ совСт – ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ reindex ΠΏΠΎΠ²Ρ€Π΅ΠΆΠ΄Ρ‘Π½Π½ΠΎΠΉ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹. Π­Ρ‚ΠΎΡ‚ совСт я встрСчал Π²ΠΎ ΠΌΠ½ΠΎΠ³ΠΈΡ… мСстах, Π½ΠΎ ΠΎΠ½ Π½Π΅ Π²Π½ΡƒΡˆΠ°Π» довСрия. Π‘Π΄Π΅Π»Π°Π΅ΠΌ reindex:

reindex table ws_log_smevlog

Мой ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΎΠΏΡ‹Ρ‚ восстановлСния Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Postgres послС сбоя (invalid page in block 4123007 of relatton base/16490)

reindex Π·Π°Π²Π΅Ρ€ΡˆΠΈΠ»ΡΡ Π±Π΅Π· ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ.

Однако это Π½Π΅ ΠΏΠΎΠΌΠΎΠ³Π»ΠΎ, VACUUM FULL Π°Π²Π°Ρ€ΠΈΠΉΠ½ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π»ΡΡ с Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎΠΉ ошибкой. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ я ΠΏΡ€ΠΈΠ²Ρ‹ΠΊ ΠΊ Π½Π΅ΡƒΠ΄Π°Ρ‡Π°ΠΌ, я стал ΠΈΡΠΊΠ°Ρ‚ΡŒ совСтов Π² ΠΈΠ½Ρ‚Π΅Ρ€Π½Π΅Ρ‚Π΅ дальшС ΠΈ наткнулся Π½Π° довольно ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΠ½ΡƒΡŽ ΡΡ‚Π°Ρ‚ΡŒΡŽ.

ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° 3: SELECT, LIMIT, OFFSET

Π’ ΡΡ‚Π°Ρ‚ΡŒΠ΅ Π²Ρ‹ΡˆΠ΅ ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π»ΠΈ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ построчно ΠΈ ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅. Для Π½Π°Ρ‡Π°Π»Π° Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π±Ρ‹Π»ΠΎ ΠΏΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ всС строки:

for ((i=0; i<"Number_of_rows_in_nodes"; i++ )); do psql -U "Username" "Database Name" -c "SELECT * FROM nodes LIMIT 1 offset $i" >/dev/null || echo $i; done

Π’ ΠΌΠΎΡ‘ΠΌ случаС Ρ‚Π°Π±Π»ΠΈΡ†Π° содСрТала 1 628 991 строк! По-Ρ…ΠΎΡ€ΠΎΡˆΠ΅ΠΌΡƒ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π±Ρ‹Π»ΠΎ ΠΏΠΎΠ·Π°Π±ΠΎΡ‚ΠΈΡ‚ΡŒΡΡ ΠΎ ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΈΡ€Π²ΠΎΠ°Π½ΠΈΠΈ Π΄Π°Π½Π½Ρ‹Ρ…, Π½ΠΎ это Ρ‚Π΅ΠΌΠ° для ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ обсуТдСния. Π‘Ρ‹Π»Π° суббота, я запустил Π²ΠΎΡ‚ эту ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ Π² tmux ΠΈ ΠΏΠΎΡˆΡ‘Π» ΡΠΏΠ°Ρ‚ΡŒ:

for ((i=0; i<1628991; i++ )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog LIMIT 1 offset $i" >/dev/null || echo $i; done

К ΡƒΡ‚Ρ€Ρƒ я Ρ€Π΅ΡˆΠΈΠ» ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ, ΠΊΠ°ΠΊ обстоят Π΄Π΅Π»Π°. К ΠΌΠΎΠ΅ΠΌΡƒ ΡƒΠ΄ΠΈΠ²Π»Π΅Π½ΠΈΡŽ, я ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ», Ρ‡Ρ‚ΠΎ Π·Π° 20 часов Π±Ρ‹Π»ΠΎ просканировано Ρ‚ΠΎΠ»ΡŒΠΊΠΎ 2% Π΄Π°Π½Π½Ρ‹Ρ…! Π–Π΄Π°Ρ‚ΡŒ 50 Π΄Π½Π΅ΠΉ я Π½Π΅ Ρ…ΠΎΡ‚Π΅Π». ΠžΡ‡Π΅Ρ€Π΅Π΄Π½ΠΎΠΉ ΠΏΠΎΠ»Π½Ρ‹ΠΉ ΠΏΡ€ΠΎΠ²Π°Π».

Но я Π½Π΅ стал ΡΠ΄Π°Π²Π°Ρ‚ΡŒΡΡ. МнС стало интСрСсно, ΠΏΠΎΡ‡Π΅ΠΌΡƒ ΠΆΠ΅ сканированиС шло Ρ‚Π°ΠΊ Π΄ΠΎΠ»Π³ΠΎ. Из Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ (ΠΎΠΏΡΡ‚ΡŒ Π½Π° postgrespro) я ΡƒΠ·Π½Π°Π»:

OFFSET ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΏΡ€ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ΅ число строк, ΠΏΡ€Π΅ΠΆΠ΄Π΅ Ρ‡Π΅ΠΌ Π½Π°Ρ‡Π°Ρ‚ΡŒ Π²Ρ‹Π΄Π°Π²Π°Ρ‚ΡŒ строки.
Если ΡƒΠΊΠ°Π·Π°Π½ΠΎ ΠΈ OFFSET, ΠΈ LIMIT, сначала систСма пропускаСт OFFSET строк, Π° Π·Π°Ρ‚Π΅ΠΌ Π½Π°Ρ‡ΠΈΠ½Π°Π΅Ρ‚ ΠΏΠΎΠ΄ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ строки для ограничСния LIMIT.

ΠŸΡ€ΠΈΠΌΠ΅Π½ΡΡ LIMIT, Π²Π°ΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Π°ΠΊΠΆΠ΅ ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ORDER BY, Ρ‡Ρ‚ΠΎΠ±Ρ‹ строки Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° Π²Ρ‹Π΄Π°Π²Π°Π»ΠΈΡΡŒ Π² ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½Π½ΠΎΠΌ порядкС. Π˜Π½Π°Ρ‡Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒΡΡ нСпрСдсказуСмыС подмноТСства строк.

ΠžΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎ, Ρ‡Ρ‚ΠΎ Π²Ρ‹ΡˆΠ΅Π½Π°ΠΏΠΈΡΠ°Π½Π½Π°Ρ ΠΊΠΎΠΌΠ°Π½Π΄Π° Π±Ρ‹Π»Π° ΠΎΡˆΠΈΠ±ΠΎΡ‡Π½ΠΎΠΉ: Π²ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, Π½Π΅ Π±Ρ‹Π»ΠΎ order by, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΌΠΎΠ³ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒΡΡ ΠΎΡˆΠΈΠ±ΠΎΡ‡Π½Ρ‹ΠΌ. Π’ΠΎ-Π²Ρ‚ΠΎΡ€Ρ‹Ρ…, Postgres сначала Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Π» ΠΏΡ€ΠΎΡΠΊΠ°Π½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈ ΠΏΡ€ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ OFFSET-строк, ΠΈ с возрастаниСм OFFSET ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ сниТалась Π±Ρ‹ Π΅Ρ‰Ρ‘ сильнСС.

ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° 4: ΡΠ½ΡΡ‚ΡŒ Π΄Π°ΠΌΠΏ Π² тСкстовом Π²ΠΈΠ΄Π΅

Π”Π°Π»Π΅Π΅ ΠΌΠ½Π΅ Π² Π³ΠΎΠ»ΠΎΠ²Ρƒ ΠΏΡ€ΠΈΡˆΠ»Π°, казалось Π±Ρ‹, гСниальная идСя: ΡΠ½ΡΡ‚ΡŒ Π΄Π°ΠΌΠΏ Π² тСкстовом Π²ΠΈΠ΄Π΅ ΠΈ ΠΏΡ€ΠΎΠ°Π½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ послСднюю Π·Π°ΠΏΠΈΡΠ°Π½Π½ΡƒΡŽ строку.

Но для Π½Π°Ρ‡Π°Π»Π°, ознакомимся со структурой Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ ws_log_smevlog:

Мой ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΎΠΏΡ‹Ρ‚ восстановлСния Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Postgres послС сбоя (invalid page in block 4123007 of relatton base/16490)

Π’ нашСм случаС Ρƒ нас Π΅ΡΡ‚ΡŒ столбСц Β«idΒ», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ содСрТал ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ (счётчик) строки. План Π±Ρ‹Π» Ρ‚Π°ΠΊΠΎΠΉ:

  1. НачинаСм ΡΠ½ΠΈΠΌΠ°Ρ‚ΡŒ Π΄Π°ΠΌΠΏ Π² тСкстовом Π²ΠΈΠ΄Π΅ (Π² Π²ΠΈΠ΄Π΅ sql-ΠΊΠΎΠΌΠ°Π½Π΄)
  2. Π’ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ снятия Π΄Π°ΠΌΠΏΠ° Π±Ρ‹ ΠΏΡ€Π΅Ρ€Π²Π°Π»ΠΎΡΡŒ ΠΈΠ·-Π·Π° ошибки, Π½ΠΎ Ρ‚Π΅ΠΊΡ‚ΠΎΠ²Ρ‹ΠΉ Ρ„Π°ΠΉΠ» всё Ρ€Π°Π²Π½ΠΎ сохранился Π±Ρ‹ Π½Π° дискС
  3. Π‘ΠΌΠΎΡ‚Ρ€ΠΈΠΌ ΠΊΠΎΠ½Π΅Ρ† тСкстового Ρ„Π°ΠΉΠ»Π°, Ρ‚Π΅ΠΌ самым ΠΌΡ‹ Π½Π°Ρ…ΠΎΠ΄ΠΈΠΌ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ (id) послСднСй строки, которая снялась ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ

Π― Π½Π°Ρ‡Π°Π» ΡΠ½ΠΈΠΌΠ°Ρ‚ΡŒ Π΄Π°ΠΌΠΏ Π² тСкстовом Π²ΠΈΠ΄Π΅:

pg_dump -U my_user -d my_database -F p -t ws_log_smevlog -f ./my_dump.dump

Бнятия Π΄Π°ΠΌΠΏΠ°, ΠΊΠ°ΠΊ ΠΈ оТидалось, прСрвался с Ρ‚ΠΎΠΉ ΠΆΠ΅ самой ошибкой:

pg_dump: Error message from server: ERROR: invalid page in block 4123007 of relatton base/16490/21396989

Π”Π°Π»Π΅Π΅ Ρ‡Π΅Ρ€Π΅Π· tail я просмотрСл ΠΊΠΎΠ½Π΅Ρ† Π΄Π°ΠΌΠΏΠ° (tail -5 ./my_dump.dump) ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ», Ρ‡Ρ‚ΠΎ Π΄Π°ΠΌΠΏ прСрвался Π½Π° строкС с id 186 525. Β«Π—Π½Π°Ρ‡ΠΈΡ‚, ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² строкС с id 186 526, ΠΎΠ½Π° битая, Π΅Ρ‘ ΠΈ Π½Π°Π΄ΠΎ ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ!Β» – ΠΏΠΎΠ΄ΡƒΠΌΠ°Π» я. Но, сдСлав запрос Π² Π±Π°Π·Ρƒ Π΄Π°Π½Π½Ρ‹Ρ…:
Β«select * from ws_log_smevlog where id=186529Β» ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ»ΠΎΡΡŒ, Ρ‡Ρ‚ΠΎ с этой строкой всё Π½ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½ΠΎβ€¦ Π‘Ρ‚Ρ€ΠΎΠΊΠΈ с индСксами 186 530 β€” 186 540 Ρ‚ΠΎΠΆΠ΅ Ρ€Π°Π±ΠΎΡ‚Π°Π»ΠΈ Π±Π΅Π· ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ. ΠžΡ‡Π΅Ρ€Π΅Π΄Π½Π°Ρ «гСниальная идСя» ΠΏΡ€ΠΎΠ²Π°Π»ΠΈΠ»Π°ΡΡŒ. ПозТС я понял, ΠΏΠΎΡ‡Π΅ΠΌΡƒ Ρ‚Π°ΠΊ ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»ΠΎ: ΠΏΡ€ΠΈ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠΈΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ· Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ ΠΎΠ½ΠΈ Π½Π΅ ΡƒΠ΄Π°Π»ΡΡŽΡ‚ΡΡ физичСски, Π° ΠΏΠΎΠΌΠ΅Ρ‡Π°ΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ Β«ΠΌΡ‘Ρ€Ρ‚Π²Ρ‹Π΅ ΠΊΠΎΡ€Ρ‚Π΅ΠΆΠΈΒ», Π΄Π°Π»Π΅Π΅ ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΡ‚ autovacuum ΠΈ ΠΏΠΎΠΌΠ΅Ρ‡Π°Π΅Ρ‚ эти строки ΡƒΠ΄Π°Π»Ρ‘Π½Π½Ρ‹ΠΌΠΈ ΠΈ Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ эти строки ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ. Для понимая, Ссли Π΄Π°Π½Π½Ρ‹Π΅ Π² Ρ‚Π°Π±Π»ΠΈΡ†Π΅ ΠΌΠ΅Π½ΡΡŽΡ‚ΡΡ ΠΈ Π²ΠΊΠ»ΡŽΡ‡Ρ‘Π½ autovacuum, Ρ‚ΠΎ ΠΎΠ½ΠΈ Π½Π΅ хранятся ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ.

ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° 5: SELECT, FROM, WHERE id=

НСудачи Π΄Π΅Π»Π°ΡŽΡ‚ нас сильнСС. НС стоит Π½ΠΈΠΊΠΎΠ³Π΄Π° ΡΠ΄Π°Π²Π°Ρ‚ΡŒΡΡ, Π½ΡƒΠΆΠ½ΠΎ ΠΈΠ΄Ρ‚ΠΈ Π΄ΠΎ ΠΊΠΎΠ½Ρ†Π° ΠΈ Π²Π΅Ρ€ΠΈΡ‚ΡŒ Π² сСбя ΠΈ свои возмоТности. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ я Ρ€Π΅ΡˆΠΈΠ» ΠΏΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ Π΅ΡˆΡ‘ ΠΎΠ΄ΠΈΠ½ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚: просто ΠΏΡ€ΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ всС записи Π² Π±Π°Π·Π΅ Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΌΡƒ. Зная структуру ΠΌΠΎΠ΅ΠΉ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ (см. Π²Ρ‹ΡˆΠ΅), Ρƒ нас Π΅ΡΡ‚ΡŒ ΠΏΠΎΠ»Π΅ id, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ являСтся ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΌ (ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹ΠΌ ΠΊΠ»ΡŽΡ‡ΠΎΠΌ). Π’ Ρ‚Π°Π±Π»ΠΈΡ†Π΅ Ρƒ нас 1 628 991 строк ΠΈ id ΠΈΠ΄ΡƒΡ‚ ΠΏΠΎ порядку, Π° это Π·Π½Π°Ρ‡ΠΈΡ‚, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ просто ΠΏΠ΅Ρ€Π΅Ρ€Π±Ρ€Π°Ρ‚ΡŒ ΠΈΡ… ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΌΡƒ:

for ((i=1; i<1628991; i=$((i+1)) )); do psql -U my_user -d my_database  -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done

Если ΠΊΡ‚ΠΎ Π½Π΅ ΠΏΠΎΠ½ΠΈΠΌΠ°Π΅Ρ‚, ΠΊΠΎΠΌΠ°Π½Π΄Π° Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ: просматриваСт построчно Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ ΠΈ отправляСт stdout Π² /dev/null, Π½ΠΎ Ссли ΠΊΠΎΠΌΠ°Π½Π΄Π° SELECT проваливаСтся, Ρ‚ΠΎ выводится тСкст ошибки (stderr отправляСтся Π² консоль) ΠΈ выводится строка, содСрТащая ΠΎΡˆΠΈΠ±ΠΊΡƒ (благодаря ||, которая ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Ρƒ select Π²ΠΎΠ·Π½ΠΈΠΊΠ»ΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ (ΠΊΠΎΠ΄ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚Π° ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ Π½Π΅ 0)).

МнС ΠΏΠΎΠ²Π΅Π·Π»ΠΎ, Ρƒ мСня Π±Ρ‹Π»ΠΈ созданы индСксы ΠΏΠΎ полю id:

Мой ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΎΠΏΡ‹Ρ‚ восстановлСния Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Postgres послС сбоя (invalid page in block 4123007 of relatton base/16490)

А это Π·Π½Π°Ρ‡ΠΈΡ‚, Ρ‡Ρ‚ΠΎ Π½Π°Ρ…ΠΎΠΆΠ΄Π΅Π½ΠΈΠ΅ строки с Π½ΡƒΠΆΠ½Ρ‹ΠΌ id Π½Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π·Π°Π½ΠΈΠΌΠ°Ρ‚ΡŒ ΠΌΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ. Π’ Ρ‚Π΅ΠΎΡ€ΠΈΠΈ Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΡΡ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ. Π§Ρ‚ΠΎ ΠΆΠ΅, запускаСм ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ Π² tmux ΠΈ ΠΈΠ΄Ρ‘ΠΌ ΡΠΏΠ°Ρ‚ΡŒ.

К ΡƒΡ‚Ρ€Ρƒ я ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ», Ρ‡Ρ‚ΠΎ просмотрСно ΠΎΠΊΠΎΠ»ΠΎ 90 000 записСй, Ρ‡Ρ‚ΠΎ составляСт Ρ‡ΡƒΡ‚ΡŒ Π±ΠΎΠ»Π΅Π΅ 5%. ΠžΡ‚Π»ΠΈΡ‡Π½Ρ‹ΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚, Ссли ΡΡ€Π°Π²Π½ΠΈΠ²Π°Ρ‚ΡŒ с ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΌ способом (2%)! Но ΠΆΠ΄Π°Ρ‚ΡŒ 20 Π΄Π½Π΅ΠΉ Π½Π΅ Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒβ€¦

ΠŸΠΎΠΏΡ‹Ρ‚ΠΊΠ° 6: SELECT, FROM, WHERE id >= and id <

Π£ Π·Π°ΠΊΠ°Π·Ρ‡ΠΈΠΊΠ° ΠΏΠΎΠ΄ Π‘Π” Π±Ρ‹Π» Π²Ρ‹Π΄Π΅Π»Π΅Π½ ΠΎΡ‚Π»ΠΈΡ‡Π½Ρ‹ΠΉ сСрвСр: двухпроцСссорный Intel Xeon E5-2697 v2, Π² нашСм располоТСнии Π±Ρ‹Π»ΠΎ Ρ†Π΅Π»Ρ‹Ρ… 48 ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²! Нагрузка Π½Π° сСрвСрС Π±Ρ‹Π»Π° срСдняя, ΠΌΡ‹ Π±Π΅Π· особых ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ ΠΌΠΎΠ³Π»ΠΈ Π·Π°Π±Ρ€Π°Ρ‚ΡŒ ΠΎΠΊΠΎΠ»ΠΎ 20-Ρ‚ΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ². ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π½ΠΎΠΉ памяти Ρ‚ΠΎΠΆΠ΅ Π±Ρ‹Π»ΠΎ достаточно: Π°ΠΆ 384 Π³ΠΈΠ³Π°Π±Π°ΠΉΡ‚!

ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ ΠΊΠΎΠΌΠ°Π½Π΄Ρƒ Π½ΡƒΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ Ρ€Π°ΡΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΠΈΡ‚ΡŒ:

for ((i=1; i<1628991; i=$((i+1)) )); do psql -U my_user -d my_database  -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done

Π’ΡƒΡ‚ ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ красивый ΠΈ элСгантный скрипт, Π½ΠΎ я Π²Ρ‹Π±Ρ€Π°Π» Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ быстрый способ распараллСливания: Ρ€Π°Π·Π±ΠΈΡ‚ΡŒ Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½ 0-1628991 Π²Ρ€ΡƒΡ‡Π½ΡƒΡŽ Π½Π° ΠΈΠ½Ρ‚Π΅Ρ€Π²Π°Π»Ρ‹ ΠΏΠΎ 100 000 записСй ΠΈ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ 16 ΠΊΠΎΠΌΠ°Π½Π΄ Π²ΠΈΠ΄Π°:

for ((i=N; i<M; i=$((i+1)) )); do psql -U my_user -d my_database  -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done

Но это Π½Π΅ всё. По ΠΈΠ΄Π΅Π΅, ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ ΠΊ Π±Π°Π·Π΅ Π΄Π°Π½Π½Ρ‹Ρ… Ρ‚ΠΎΠΆΠ΅ ΠΎΡ‚Π½ΠΈΠΌΠ°Π΅Ρ‚ ΠΊΠ°ΠΊΠΎΠ΅-Ρ‚ΠΎ врСмя ΠΈ систСмныС рСсурсы. ΠŸΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Ρ‚ΡŒ 1 628 991 Π±Ρ‹Π»ΠΎ Π½Π΅ ΠΎΡ‡Π΅Π½ΡŒ Ρ€Π°Π·ΡƒΠΌΠ½ΠΎ, ΡΠΎΠ³Π»Π°ΡΠΈΡ‚Π΅ΡΡŒ. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ Π΄Π°Π²Π°ΠΉΡ‚Π΅ ΠΏΡ€ΠΈ ΠΎΠ΄Π½ΠΎΠΌ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΈ ΠΈΠ·Π²Π»Π΅ΠΊΠ°Ρ‚ΡŒ 1000 строк вмСсто ΠΎΠ΄Π½ΠΎΠΉ. Π’ ΠΈΡ‚ΠΎΠ³Π΅ ΠΊΠΎΠΌΠ°Π½Π΄Π° ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΈΠ»ΠΎΠ°ΡΡŒ Π² это:

for ((i=N; i<M; i=$((i+1000)) )); do psql -U my_user -d my_database  -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done

ΠžΡ‚ΠΊΡ€Ρ‹Π²Π°Π΅ΠΌ 16 ΠΎΠΊΠΎΠ½ Π² сСссии tmux ΠΈ запускаСм ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹:

1) for ((i=0; i<100000; i=$((i+1000)) )); do psql -U my_user -d my_database  -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done
2) for ((i=100000; i<200000; i=$((i+1000)) )); do psql -U my_user -d my_database  -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done
…
15) for ((i=1400000; i<1500000; i=$((i+1000)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done
16) for ((i=1500000; i<1628991; i=$((i+1000)) )); do psql -U my_user -d my_database  -c "SELECT * FROM ws_log_smevlog where id>=$i and id<$((i+1000))" >/dev/null || echo $i; done

Π§Π΅Ρ€Π΅Π· дСнь я ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ» ΠΏΠ΅Ρ€Π²Ρ‹Π΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹! А ΠΈΠΌΠ΅Π½Π½ΠΎ (значСния XXX ΠΈ ZZZ ΡƒΠΆΠ΅ Π½Π΅ ΡΠΎΡ…Ρ€Π°Π½ΠΈΠ»ΠΈΡΡŒ):

ERROR:  missing chunk number 0 for toast value 37837571 in pg_toast_106070
829000
ERROR:  missing chunk number 0 for toast value XXX in pg_toast_106070
829000
ERROR:  missing chunk number 0 for toast value ZZZ in pg_toast_106070
146000

Π­Ρ‚ΠΎ Π·Π½Π°Ρ‡ΠΈΡ‚, Ρ‡Ρ‚ΠΎ Ρƒ нас Ρ‚Ρ€ΠΈ строки содСрТат ΠΎΡˆΠΈΠ±ΠΊΡƒ. id ΠΏΠ΅Ρ€Π²ΠΎΠΉ ΠΈ Π²Ρ‚ΠΎΡ€ΠΎΠΉ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ½ΠΎΠΉ записи Π½Π°Ρ…ΠΎΠ΄ΠΈΠ»ΠΈΡΡŒ ΠΌΠ΅ΠΆΠ΄Ρƒ 829 000 ΠΈ 830 000, id Ρ‚Ρ€Π΅Ρ‚ΡŒΠ΅ΠΉ – ΠΌΠ΅ΠΆΠ΄Ρƒ 146 000 ΠΈ 147 000. Π”Π°Π»Π΅Π΅ Π½Π°ΠΌ прСдстояло просто Π½Π°ΠΉΡ‚ΠΈ Ρ‚ΠΎΡ‡Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ id ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ½Ρ‹Ρ… записСй. Для этого просматриваСм наш Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½ с ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ½Ρ‹ΠΌΠΈ записями с шагом 1 ΠΈ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€ΡƒΠ΅ΠΌ id:

for ((i=829000; i<830000; i=$((i+1)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done
829417
ERROR:  unexpected chunk number 2 (expected 0) for toast value 37837843 in pg_toast_106070
829449
for ((i=146000; i<147000; i=$((i+1)) )); do psql -U my_user -d my_database -c "SELECT * FROM ws_log_smevlog where id=$i" >/dev/null || echo $i; done
829417
ERROR:  unexpected chunk number ZZZ (expected 0) for toast value XXX in pg_toast_106070
146911

Бчастливый Ρ„ΠΈΠ½Π°Π»

ΠœΡ‹ нашли ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ½Ρ‹Π΅ строки. Π—Π°Ρ…ΠΎΠ΄ΠΈΠΌ Π² Π±Π°Π·Ρƒ Ρ‡Π΅Ρ€Π΅Π· psql ΠΈ ΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ ΠΈΡ… ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ:

my_database=# delete from ws_log_smevlog where id=829417;
DELETE 1
my_database=# delete from ws_log_smevlog where id=829449;
DELETE 1
my_database=# delete from ws_log_smevlog where id=146911;
DELETE 1

К ΠΌΠΎΠ΅ΠΌΡƒ ΡƒΠ΄ΠΈΠ²Π»Π΅Π½ΠΈΡŽ, записи ΡƒΠ΄Π°Π»ΠΈΠ»ΠΈΡΡŒ Π±Π΅Π· ΠΊΠ°ΠΊΠΈΡ…-Π»ΠΈΠ±ΠΎ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ Π΄Π°ΠΆΠ΅ Π±Π΅Π· ΠΎΠΏΡ†ΠΈΠΈ zero_damaged_pages.

Π—Π°Ρ‚Π΅ΠΌ я ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΠ»ΡΡ ΠΊ Π±Π°Π·Π΅, сдСлал VACUUM FULL (Π΄ΡƒΠΌΠ°ΡŽ Π΄Π΅Π»Π°Ρ‚ΡŒ Π±Ρ‹Π»ΠΎ Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ), ΠΈ, Π½Π°ΠΊΠΎΠ½Π΅Ρ†, ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ снял Π±Π΅ΠΊΠ°ΠΏ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ pg_dump. Π”Π°ΠΌΠΏ снялся Π±Π΅Π· ΠΊΠ°ΠΊΠΈΡ… Π»ΠΈΠ±ΠΎ ошибок! ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ ΡƒΠ΄Π°Π»ΠΎΡΡŒ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ Ρ‚Π°ΠΊΠΈΠΌ Π²ΠΎΡ‚ Ρ‚ΡƒΠΏΠ΅ΠΉΡˆΠΈΠΌ способом. Радости Π½Π΅ Π±Ρ‹Π»ΠΎ ΠΏΡ€Π΅Π΄Π΅Π»Π°, послС ΡΡ‚ΠΎΠ»ΡŒΠΊΠΈΡ… Π½Π΅ΡƒΠ΄Π°Ρ‡ ΡƒΠ΄Π°Π»ΠΎΡΡŒ Π½Π°ΠΉΡ‚ΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅!

Благодарности ΠΈ Π·Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

Π’ΠΎΡ‚ Ρ‚Π°ΠΊΠΎΠΉ получился ΠΌΠΎΠΉ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΎΠΏΡ‹Ρ‚ восстановлСния Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΉ Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Postgres. Π­Ρ‚ΠΎΡ‚ ΠΎΠΏΡ‹Ρ‚ я запомню Π½Π°Π΄ΠΎΠ»Π³ΠΎ.

Ну ΠΈ напослСдок, Ρ…ΠΎΡ‚Π΅Π» Π±Ρ‹ ΡΠΊΠ°Π·Π°Ρ‚ΡŒ спасибо ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ PostgresPro Π·Π° ΠΏΠ΅Ρ€Π΅Π²Π΅Π΄Ρ‘Π½Π½ΡƒΡŽ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡŽ Π½Π° русский язык ΠΈ Π·Π° ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ бСсплатныС online-курсы, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΡ‡Π΅Π½ΡŒ сильно ΠΏΠΎΠΌΠΎΠ³Π»ΠΈ Π²ΠΎ врСмя Π°Π½Π°Π»ΠΈΠ·Π° ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com