ในกรณีที่ง่ายที่สุดเมื่อเราแทรกแถวใหม่ลงในตาราง (และการทำธุรกรรม) มันจะปรากฏให้เห็นในการทำธุรกรรมที่ตามมาทั้งหมด ดูxmax
เป็น 0 ในตัวอย่างนี้:
CREATE TABLE vis (
id serial,
is_active boolean
);
INSERT INTO vis (is_active) VALUES (FALSE);
SELECT ctid, xmin, xmax, * FROM vis;
ctid │xmin │ xmax │ id │ is_active
───────┼─────┼──────┼────┼───────────
(0,1) │2699 │ 0 │ 1 │ f
เมื่อเราอัปเดต (เนื่องจากการตั้งค่าสถานะถูกกำหนดFALSE
โดยไม่ได้ตั้งใจ) จะมีการเปลี่ยนแปลงเล็กน้อย:
UPDATE vis SET is_active = TRUE;
SELECT ctid, xmin, xmax, * FROM vis;
ctid │ xmin │ xmax │ id │ is_active
──────┼──────┼──────┼────┼───────────
(0,2) │ 2700 │ 0 │ 1 │ t
ตามโมเดลMVCC ที่ใช้ PostgreSQL จะมีการเขียนฟิสิคัลแถวใหม่และอันเก่าไม่ถูกต้อง (สามารถเห็นได้จากctid
) รายการใหม่ยังคงปรากฏให้เห็นในธุรกรรมที่ตามมาทั้งหมด
ขณะนี้มีสิ่งที่น่าสนใจเกิดขึ้นเมื่อเราย้อนกลับUPDATE
:
BEGIN;
UPDATE vis SET is_active = TRUE;
ROLLBACK;
SELECT ctid, xmin, xmax, * FROM vis;
ctid │ xmin │ xmax │ id │ is_active
───────┼──────┼──────┼────┼───────────
(0,2) │ 2700 │ 2702 │ 1 │ t
เวอร์ชันแถวยังคงเหมือนเดิม แต่ตอนนี้xmax
ถูกตั้งค่าเป็นบางอย่าง อย่างไรก็ตามสิ่งนี้ธุรกรรมที่ตามมาสามารถเห็นแถวนี้ (ไม่เปลี่ยนแปลง)
หลังจากที่ได้อ่านเกี่ยวกับเรื่องนี้แล้วคุณอาจจะเข้าใจถึงการมองเห็นของแถว มีแผนที่การมองเห็นแต่จะบอกได้เฉพาะเมื่อมองเห็นทั้งหน้า - แน่นอนว่ามันไม่สามารถใช้งานได้ในระดับแถว (tuple) แล้วมีบันทึกการกระทำ (aka clog
) - แต่ Postgres จะหาวิธีได้อย่างไรหากต้องเข้าชม
ฉันตัดสินใจที่จะดูบิตของ infomaskเพื่อดูว่าการมองเห็นใช้งานได้จริงอย่างไร จะเห็นพวกเขาวิธีที่ง่ายที่สุดคือการใช้ส่วนขยาย pageinspect เพื่อค้นหาว่าบิตใดถูกตั้งค่าฉันได้สร้างตารางเพื่อจัดเก็บ:
CREATE TABLE infomask (
i_flag text,
i_bits bit(16)
);
INSERT INTO infomask
VALUES
('HEAP_HASNULL', x'0001'::bit(16)),
('HEAP_HASVARWIDTH', x'0002'::bit(16)),
('HEAP_HASEXTERNAL', x'0004'::bit(16)),
('HEAP_HASOID', x'0008'::bit(16)),
('HEAP_XMAX_KEYSHR_LOCK', x'0010'::bit(16)),
('HEAP_COMBOCID', x'0020'::bit(16)),
('HEAP_XMAX_EXCL_LOCK', x'0040'::bit(16)),
('HEAP_XMAX_LOCK_ONLY', x'0080'::bit(16)),
('HEAP_XMIN_COMMITTED', x'0100'::bit(16)),
('HEAP_XMIN_INVALID', x'0200'::bit(16)),
('HEAP_XMAX_COMMITTED', x'0400'::bit(16)),
('HEAP_XMAX_INVALID', x'0800'::bit(16)),
('HEAP_XMAX_IS_MULTI', x'1000'::bit(16)),
('HEAP_UPDATED', x'2000'::bit(16)),
('HEAP_MOVED_OFF', x'4000'::bit(16)),
('HEAP_MOVED_IN', x'8000'::bit(16)),
('HEAP_XACT_MASK', x'FFF0'::bit(16));
จากนั้นตรวจสอบสิ่งที่อยู่ในvis
ตารางของฉัน- โปรดทราบว่าpageinspect
จะแสดงเนื้อหาทางกายภาพของกองดังนั้นไม่เพียง แต่ส่งกลับแถวที่มองเห็นได้:
SELECT t_xmin, t_xmax, string_agg(i_flag, ', ') FILTER (WHERE (t_infomask::bit(16) & i_bits)::integer::boolean)
FROM heap_page_items(get_raw_page('vis', 0)),
infomask
GROUP BY t_xmin, t_xmax;
t_xmin │ t_xmax │ string_agg
────────┼────────┼──────────────────────────────────────────────────────
2699 │ 2700 │ HEAP_XMIN_COMMITTED, HEAP_XMAX_COMMITTED
2700 │ 2702 │ HEAP_XMIN_COMMITTED, HEAP_XMAX_INVALID, HEAP_UPDATED
2702 │ 0 │ HEAP_XMIN_INVALID, HEAP_XMAX_INVALID, HEAP_UPDATED
สิ่งที่ฉันเข้าใจจากข้างต้นคือรุ่นแรกมีชีวิตขึ้นมาด้วยรายการ 2699 จากนั้นแทนที่ด้วยเวอร์ชันใหม่ที่ 2700
จากนั้นรุ่นถัดไปที่ยังมีชีวิตอยู่ตั้งแต่ 2700 มีความพยายามย้อนกลับไปUPDATE
ใน 2702 จากHEAP_XMAX_INVALID
. สุดท้ายก็ไม่เคยเกิดจริงๆที่แสดงโดย
HEAP_XMIN_INVALID
ดังนั้นการคาดเดาจากกรณีข้างต้นกรณีแรกและสุดท้ายชัดเจน - พวกเขาไม่สามารถมองเห็นธุรกรรม 2703 หรือสูงกว่าได้อีกต่อไป
คนที่สองจะต้องมีการมองขึ้นบาง - clog
ฉันคิดว่ามันเป็นบันทึกการกระทำอาคา
หากต้องการทำให้ปัญหายุ่งยากซับซ้อนยิ่งขึ้นUPDATE
ผลลัพธ์ที่ตามมาจะเป็นดังนี้:
t_xmin │ t_xmax │ string_agg
────────┼────────┼────────────────────────────────────────────────────
2699 │ 2700 │ HEAP_XMIN_COMMITTED, HEAP_XMAX_COMMITTED
2702 │ 0 │ HEAP_XMIN_INVALID, HEAP_XMAX_INVALID, HEAP_UPDATED
2703 │ 0 │ HEAP_XMAX_INVALID, HEAP_UPDATED
2700 │ 2703 │ HEAP_XMIN_COMMITTED, HEAP_UPDATED
ที่นี่ฉันเห็นผู้สมัครสองคนที่สามารถมองเห็นได้ ดังนั้นในที่สุดนี่คือคำถามของฉัน:
- การสันนิษฐานของฉัน
clog
คือสถานที่ที่จะมองเพื่อกำหนดทัศนวิสัยในกรณีเหล่านี้หรือไม่? - ธงที่ (หรือการรวมกันของธง) บอกระบบเพื่อเข้าชม
clog
? - มีวิธีการตรวจสอบสิ่งที่อยู่ภายใน
clog
? มีการกล่าวถึงclog
ความเสียหายใน Postgres รุ่นก่อนหน้าและมีคำใบ้ว่าสามารถสร้างไฟล์ปลอมด้วยตนเองได้ ข้อมูลชิ้นนี้จะช่วยได้มาก