รับวันที่แก้ไขล่าสุดของตารางฐานข้อมูล PostgreSQL


35

ฉันพยายามรับเมื่อตารางของฉันถูกแก้ไขโดยตรวจสอบวันที่แก้ไขไฟล์ตามที่อธิบายไว้ในคำตอบนี้ แต่ผลลัพธ์ไม่ถูกต้องเสมอไป วันที่แก้ไขไฟล์อัปเดตในหลายนาทีหลังจากฉันอัปเดตตาราง มันเป็นพฤติกรรมที่ถูกต้องหรือไม่ PostgreSQL จัดเก็บการดัดแปลงตารางในแคชแล้วล้างออกไปยังฮาร์ดไดรฟ์หรือไม่

ดังนั้นฉันจะได้รับวันที่แก้ไขล่าสุดที่ถูกต้องของตารางได้อย่างไร (สมมติว่าการแก้ไขสูญญากาศอัตโนมัติก็โอเคด้วย)

ฉันใช้ PostgreSQL 9.2 ภายใต้ Linux Centos 6.2 x64


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

แนวคิดหนึ่งคือข้อมูลที่เก็บไว้ในไฟล์ WAL จะถูกเขียนไปยังไฟล์ข้อมูลบางครั้ง (สั้นหรือนานกว่า) หลังจากทำธุรกรรม หากคุณต้องการคุณสามารถเรียกแคชนี้ได้ :) มิฉะนั้นฉันจะทำตามที่ @a_horse_with_no_name พูด
dezso

คำตอบ:


35

ไม่มีระเบียนที่เชื่อถือได้และเชื่อถือได้ของเวลาที่แก้ไขล่าสุดของตาราง การใช้ relfilenode นั้นผิดด้วยเหตุผลหลายประการ:

  • ตอนแรกการเขียนจะถูกบันทึกลงในบันทึกการเขียนหัว (WAL) จากนั้นก็ขี้เกียจไปที่ฮีป (ไฟล์ตาราง) เมื่อเร็กคอร์ดอยู่ใน WAL แล้ว Pg ก็ไม่รีบเร่งที่จะเขียนมันไปยังกองและมันอาจจะไม่ถูกเขียนจนกว่าจะถึงด่านต่อไป

  • ตารางที่ใหญ่กว่ามีส้อมหลายอันคุณต้องตรวจสอบส้อมทั้งหมดและเลือกการประทับเวลาใหม่ล่าสุด

  • วิSELECTสามารถสร้างกิจกรรมการเขียนไปยังตารางพื้นฐานเนื่องจากการตั้งค่า hint-bit;

  • autovaccum และการบำรุงรักษาอื่น ๆ ที่ไม่ได้เปลี่ยนข้อมูลที่ผู้ใช้มองเห็นยังคงแก้ไขไฟล์ความสัมพันธ์;

  • การดำเนินการบางอย่างเช่นvaccum fullจะแทนที่ relfilenode อาจไม่ใช่ที่ที่คุณคาดหวังหากคุณพยายามมองมันไปพร้อม ๆ กันโดยไม่ต้องล็อคที่เหมาะสม

ตัวเลือกน้อย

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

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

ทางเลือกที่น่ากลัวเล็กน้อยน้อยคือการใช้และLISTEN NOTIFYมีกระบวนการ daemon ภายนอกเชื่อมต่อกับ PostgreSQL และLISTENสำหรับเหตุการณ์ ใช้ON INSERT OR UPDATE OR DELETEทริกเกอร์เพื่อส่งNOTIFYs เมื่อตารางเปลี่ยนแปลงโดยมีตาราง oid เป็น payload แจ้งเตือน สิ่งเหล่านี้จะถูกส่งเมื่อมีการทำธุรกรรม ภูตของคุณสามารถสะสมการแจ้งเตือนการเปลี่ยนแปลงและขี้เกียจเขียนกลับไปที่ตารางในฐานข้อมูล หากระบบขัดข้องคุณจะสูญเสียการบันทึกการแก้ไขล่าสุด แต่ก็ไม่เป็นไรคุณแค่ถือว่าตารางทั้งหมดเป็นแบบที่เพิ่งแก้ไขถ้าคุณเริ่มต้นใหม่หลังจากเกิดความผิดพลาด

เพื่อหลีกเลี่ยงปัญหาที่เกิดขึ้นพร้อมกันที่เลวร้ายที่สุดคุณสามารถบันทึกการเปลี่ยนแปลงการประทับเวลาโดยใช้before insert or update or delete or truncate on tablename for each statement executeทริกเกอร์โดยทั่วไปจะใช้ความสัมพันธ์ oid เป็นพารามิเตอร์ สิ่งนี้จะแทรก(relation_oid, timestamp)คู่ลงในตารางการบันทึกการเปลี่ยนแปลง จากนั้นคุณมีกระบวนการผู้ช่วยในการเชื่อมต่อที่แยกต่างหากหรือเรียกเป็นระยะ ๆ โดยแอปของคุณรวมตารางนั้นสำหรับข้อมูลล่าสุดรวมเข้ากับตารางสรุปการเปลี่ยนแปลงล่าสุดและตัดทอนตารางบันทึก ข้อได้เปรียบเพียงข้อเดียวของวิธีนี้ในการฟัง / แจ้งเตือนคือไม่ให้ข้อมูลสูญหายเมื่อเกิดการขัดข้อง - แต่ก็มีประสิทธิภาพน้อยลงเช่นกัน

อีกวิธีหนึ่งที่อาจจะมีการเขียนฟังก์ชั่นการขยาย C ที่ใช้ (เช่น) ProcessUtility_hook, ExecutorRun_hookฯลฯ ที่จะดักเปลี่ยนแปลงตารางและการปรับปรุงสถิติอย่างเฉื่อยชา ฉันไม่ได้ดูว่ามันจะเป็นไปได้จริง ดูตัวเลือก _hook ต่างๆในแหล่งที่มา

วิธีที่ดีที่สุดคือการแก้ไขรหัสสถิติเพื่อบันทึกข้อมูลนี้และส่งแพตช์ไปยัง PostgreSQL เพื่อรวมไว้ในคอร์ อย่าเพิ่งเริ่มต้นด้วยการเขียนโค้ด เพิ่มความคิดของคุณในแฮ็คเกอร์เมื่อคุณคิดพอที่จะมีวิธีที่ชัดเจนที่จะทำ (เช่นเริ่มจากการอ่านโค้ดอย่าเพิ่งโพสต์ถามว่า "ฉันจะทำอย่างไร ... ") อาจเป็นการดีที่จะเพิ่มเวลาที่อัปเดตครั้งล่าสุดpg_stat_...แต่คุณจะต้องโน้มน้าวให้ชุมชนเห็นว่ามันคุ้มค่ากับค่าใช้จ่ายหรือให้วิธีการติดตามทางเลือก - และคุณต้องเขียนรหัสเพื่อเก็บสถิติและ ส่งแพทช์เพราะมีเพียงคนที่ต้องการคุณลักษณะนี้เท่านั้นที่จะไปสนใจ

ฉันจะทำยังไง

หากฉันต้องทำสิ่งนี้และไม่มีเวลาเขียนโปรแกรมแก้ไขเพื่อทำอย่างถูกต้องฉันอาจใช้วิธีการฟัง / แจ้งเตือนที่อธิบายไว้ข้างต้น

อัปเดตสำหรับ PostgreSQL 9.5 กำหนดการประทับเวลา

ปรับปรุง : PostgreSQL 9.5 มีกระทำการประทับเวลา หากคุณเปิดใช้งานไว้ในpostgresql.conf(และเคยทำเช่นนั้นในอดีต) คุณสามารถตรวจสอบการประทับเวลาสำหรับแถวที่มีค่ามากที่สุดxminในการประมาณเวลาที่แก้ไขล่าสุด มันเป็นเพียงการประมาณค่าเพราะหากแถวล่าสุดถูกลบไปแถวนั้นจะไม่ถูกนับ

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


17

PostgreSQL 9.5 ให้เราติดตามการคอมมิทที่แก้ไขล่าสุด

  1. ตรวจสอบแทร็กการกระทำเปิดหรือปิดโดยใช้แบบสอบถามต่อไปนี้

    show track_commit_timestamp;
  2. ถ้ามันกลับเป็น "ON" ให้ไปที่ขั้นตอนที่ 3 แก้ไข postgresql.conf

    cd /etc/postgresql/9.5/main/
    vi postgresql.conf

    เปลี่ยนแปลง

    track_commit_timestamp = off

    ไปยัง

    track_commit_timestamp = on

    รีบูทระบบ

    ทำซ้ำขั้นตอนที่ 1

  3. ใช้แบบสอบถามต่อไปนี้เพื่อติดตามการกระทำครั้งล่าสุด

    SELECT pg_xact_commit_timestamp(xmin), * FROM  YOUR_TABLE_NAME;
    
    SELECT pg_xact_commit_timestamp(xmin), * FROM YOUR_TABLE_NAME where COLUMN_NAME=VALUE;

1
คุณไม่ต้องรีบูทระบบในขั้นตอนที่ 2 เพียงแค่เริ่มกระบวนการใหม่ sudo service postgresql restartเช่น
ijoseph

3

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


ฉันไม่แน่ใจว่าฉันเข้าใจวิธีการนี้ตอบคำถาม ใช่ข้อมูลถูกเก็บไว้ในบันทึกการทำธุรกรรม แต่นั่นไม่ได้หมายความว่าจะสามารถแก้ไขเวลาสำหรับตารางที่ระบุได้อย่างง่ายดาย ( หากเนื้อหานั้นยังอยู่ในบันทึกหนึ่งสามารถแยกวิเคราะห์บันทึกได้ อย่างรวดเร็ว).
Charles Duffy

แน่นอนคุณจะได้รับข้อมูลที่จำเป็นทั้งหมดจากบันทึก แต่คำถามถูกนำไปยังเวลาของดาต้าไทล์ - การทำให้ไฟล์ข้อมูลเกิดขึ้นได้แบบสุ่ม - สองสามวินาที - ไม่กี่นาที (สูงสุด 1 ชั่วโมง) หลังจากกระทำ
Pavel Stehule

ความพยายามของ OP เองคือการดูไฟล์ แต่เจตนาที่แท้จริงของพวกเขานั้นชัดเจนเพื่อให้ได้ตาราง mtime แต่ใช่ฉันเข้าใจว่าคุณมาจากที่นี่ (อธิบายว่าทำไมสิ่งที่พวกเขาทำไม่ทำงาน) ตอนนี้
Charles Duffy

2

ฉันมีข้อกำหนดเกือบเหมือนกันเพื่อรักษาแคชของบางตารางในแอปพลิเคชันไคลเอนต์ ฉันพูดเกือบเพราะฉันไม่จำเป็นต้องรู้เวลาของการปรับเปลี่ยนครั้งล่าสุด แต่เพียงเพื่อตรวจสอบว่ามีอะไรบางอย่างเปลี่ยนไปตั้งแต่ครั้งล่าสุดที่แคชถูกซิงโครไนซ์

นี่คือแนวทางของฉัน:

ระบุว่าคุณมีid(PK), created_on(การแทรกเวลาประทับ) และupdated_on(อัปเดตการประทับเวลาอาจเป็นค่า NULL) ในทุกตารางคุณสามารถ

SELECT id,greatest(created_on,updated_on) FROM %s ORDER BY greatest(created_on,updated_on) DESC LIMIT 1;

หากคุณเชื่อมต่อสิ่งนี้และเพิ่มจำนวนแถวคุณสามารถสร้างแท็กเวอร์ชันที่ดูเหมือนcount:id#timestampและจะไม่ซ้ำกันสำหรับข้อมูลทุกรุ่นในตาราง

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