วิธีการเรียกคืนพื้นที่ดิสก์บน PostgreSQL


25

ฉันมีการติดตั้งฐานข้อมูลท้องถิ่น 9.1 กับตารางน้อยซึ่งมี cca บันทึก 300 mio และฐานข้อมูลเพิ่มขึ้นเป็นประมาณ 20 GB หลังจากนั้นฉันออกdelete fromคำสั่งให้ลบระเบียนทั้งหมดจากมัน (ฉันควรจะใช้truncateแต่ฉันก็ไม่รู้) ดังนั้นฉันจึงสูญญากาศเต็มในฐานข้อมูลของฉันเพื่อเรียกคืนพื้นที่ดิสก์ แต่ก็ไม่ได้ช่วย ปัญหาของฉันดูเหมือนกับปัญหานี้แต่ไม่มีวิธีแก้ไข ฉันได้ตรวจสอบเธรดและเอกสารนี้แล้วใน"การกู้คืนพื้นที่ว่างในดิสก์"แต่ยังหาวิธีแก้ปัญหาไม่ได้ ฉันใช้รหัสนี้เพื่อรับขนาดของตารางทั้งหมด

 SELECT nspname || '.' || relname AS "relation",
 pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"
 FROM pg_class C
 LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
 WHERE nspname NOT IN ('pg_catalog', 'information_schema')
 AND C.relkind <> 'i'
 AND nspname !~ '^pg_toast'
 ORDER BY pg_total_relation_size(C.oid) DESC
 LIMIT 15;

อย่างไรก็ตามมีจำนวนน้อยกว่า 1GB

SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size FROM pg_database 

ยังคงแสดงประมาณ 20 GB คำแนะนำใด ๆ ที่ชื่นชมมาก


ข้อความค้นหาขนาดของคุณไม่รวม: ดัชนีตารางในpg_catalogและตารางinformation_schemaมา ดังนั้นลองดูว่ามันเป็นของใด ๆ โดยการลบข้อ จำกัด เหล่านั้นในWHEREข้อ โปรดแสดงเวอร์ชัน PostgreSQL ที่แน่นอนของคุณ ( SELECT version()) และสิ่งที่คุณทำเพื่อ "ดูดข้อมูลฐานข้อมูลทั้งหมด" เช่นคำสั่งที่แน่นอน หากเป็นไปได้ให้เรียกใช้VACUUM FULL VERBOSE;(ไม่มีข้อโต้แย้ง) และวางผลลัพธ์ที่ใดก็ได้จากนั้นลิงก์ไปที่นี่
Craig Ringer

ลองวางฐานข้อมูล คุณอาจลองทิ้งฐานข้อมูลแล้วกู้คืนมันจะทิ้งขยะ
jb

1
@jb มันใช้ได้ แต่ก็ไม่จำเป็น ดีกว่าที่จะเรียนรู้ว่าปัญหาคืออะไร
Craig Ringer

คำตอบ:


22

แม้ว่าคุณจะไม่ได้ระบุ แต่ฉันถือว่าการอ้างอิงของคุณไปยังเอกสารที่คุณได้ติดตามว่าคุณได้ทำ VACUUM FULL บนฐานข้อมูลและ / หรือตารางที่ได้รับผลกระทบแล้ว คุณยังไม่ได้ระบุรุ่น postgresql ที่คุณกำลังใช้ - ฉันจะถือว่ามันเป็น> 9.0 (VACUUM FULL ทำตัวต่างไปก่อนหน้านี้)

VACUUM FULLจะเขียนตารางที่ได้รับผลกระทบลงในไฟล์ใหม่แล้วลบไฟล์เก่า อย่างไรก็ตามหากกระบวนการใด ๆ ที่ยังคงมีไฟล์เก่าเปิดอยู่ระบบปฏิบัติการจะไม่ลบไฟล์จริง ๆ - จนกว่ากระบวนการสุดท้ายจะปิดมัน

หากใช้งานได้จริงการรีสตาร์ทฐานข้อมูลจะทำให้แน่ใจว่าไฟล์ที่เปิดอยู่ทั้งหมดถูกปิด

หากวิธีนี้ไม่สามารถใช้งานได้คุณอาจตรวจสอบได้ว่านี่เป็นปัญหาของคุณหรือไม่และดูว่ากระบวนการใดบ้างที่เปิดไฟล์

หากใช้ Linux (หรือระบบอื่น ๆ ที่คล้าย Unix) คุณสามารถใช้คำสั่ง 'lsof' เพื่อรับรายการไฟล์ทั้งหมดที่เปิดในทุกกระบวนการ ไฟล์ที่เปิดอยู่ แต่ที่ถูกลบไปแล้วจะมี '(ลบ)' ต่อท้ายชื่อไฟล์ ดังนั้นคุณสามารถ grep ผลลัพธ์ของ lsof, ค้นหาไฟล์ที่ถูกลบ, เช่นนี้:

sudo lsof -u postgres | grep 'deleted'

หากระบุกระบวนการที่ยังคงเปิดไฟล์เก่าอยู่คุณสามารถใช้ pg_terminate_backend เพื่อยุติกระบวนการดังกล่าว:

SELECT pg_terminate_backend(xxx);

โดยที่ xxx คือ PID ของกระบวนการซึ่งพบในเอาต์พุต lsof

หากใช้ Windows อาจใช้หลักการเดียวกันนี้ได้เนื่องจาก postgres จะเปิดไฟล์โดยใช้แฟล็ก FILE_SHARE_DELETE ซึ่งอนุญาตให้ลบไฟล์ที่เปิดในกระบวนการอื่นได้ 'การจับคำสั่ง' เป็นเทียบเท่าหยาบของ lsof แม้ว่าผมไม่แน่ใจว่าถ้าคุณสามารถบอกได้ว่าไฟล์ที่ถูกลบหรือไม่ให้ทำงานบางอย่างเพิ่มเติมอาจจะต้อง

เป็นอีกคำถามหนึ่งว่าทำไมกระบวนการดังกล่าวจะถูกระงับลงบนตัวจัดการไฟล์เก่า อย่างไรก็ตามในเธรดที่คุณยกมาในคำถามของคุณทอมเลนดูเหมือนจะบอกเป็นนัยว่ามันสามารถเกิดขึ้นได้


ฉันต้องรีบคืนพื้นที่ดิสก์อย่างเร่งด่วนดังนั้นฉันจึงวางฐานข้อมูลและเรียกคืนจากการสำรองข้อมูล อย่างไรก็ตาม "วิธีการ" แก้ปัญหานี้ยังมีค่ามากสำหรับกรณีในอนาคต ฐานข้อมูลของฉันคือ 9.1, ชนะ 8 64 บิต, การตั้งชื่อไฟล์ (กรณีของไฟล์ที่เปิด) ใช้แบบเดียวกับใน linux หรือไม่?

@arcull ตกลงฉันไม่ทราบว่าคุณกำลังใช้ Windows ฉันได้เพิ่มข้อมูลลงในคำตอบเกี่ยวกับวิธีการที่ใช้กับ Windows หากคุณคิดว่าอาจเป็นคำตอบที่มีประโยชน์โปรดพิจารณาการเลื่อนตำแหน่งเนื่องจากจะทำให้ผู้อื่นสามารถค้นหาได้ง่ายขึ้น
อันตราย
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.