Score:2

จะดีบักข้อผิดพลาดการแบ่งเซ็กเมนต์ PostgreSQL ได้อย่างไร

ธง ng

ฉันมีอินสแตนซ์ PostgreSQL 13 ที่หยุดทำงาน:

บันทึก: กระบวนการของเซิร์ฟเวอร์ (PID 10722) ถูกยกเลิกโดยสัญญาณ 11: ข้อผิดพลาดของการแบ่งส่วน
รายละเอียด: กระบวนการทำงานล้มเหลว: COMMIT
LOG: ยุติกระบวนการเซิร์ฟเวอร์อื่น ๆ ที่ใช้งานอยู่
คำเตือน: ยุติการเชื่อมต่อเนื่องจากการขัดข้องของกระบวนการเซิร์ฟเวอร์อื่น
รายละเอียด: postmaster ได้สั่งให้กระบวนการของเซิร์ฟเวอร์นี้ย้อนกลับธุรกรรมปัจจุบันและออก เนื่องจากกระบวนการของเซิร์ฟเวอร์อื่นออกอย่างผิดปกติและอาจทำให้หน่วยความจำที่ใช้ร่วมกันเสียหาย

ฉันอัปเดตแล้ว /etc/postgresql/13/main/pg_ctl.conf เพื่อรวมการถ่ายโอนข้อมูลหลัก

pg_ctl_options = '--ไฟล์หลัก'

และเริ่มต้นใหม่ postgresql บริการ. ตอนนี้ดูเหมือนว่าจะอนุญาตการถ่ายโอนข้อมูลหลัก:

$ สำหรับ f ใน `pgrep postgres`; ทำ cat /proc/$f/limits | แกน grep; เสร็จแล้ว
ขนาดไฟล์หลักสูงสุดไม่จำกัดจำนวนไบต์ไม่จำกัด 

จีดีบี backtrace ให้ผลลัพธ์ต่อไปนี้

$ gdb /usr/lib/postgresql/13/bin/postgres 13/main/core.postgres.12264

โปรแกรมสิ้นสุดด้วยสัญญาณ SIGSEGV, ข้อผิดพลาดของการแบ่งส่วน
#0 slot_deform_heap_tuple (natts=5, offp=0x557cc2e60720, tuple=<เพิ่มประสิทธิภาพออก>, slot=0x557cc2e606d8) ที่ ./build/../src/backend/executor/execTuples.c:930
930 ./build/../src/backend/executor/execTuples.c: ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว
(gdb) บต
#0 slot_deform_heap_tuple (natts=5, offp=0x557cc2e60720, tuple=<เพิ่มประสิทธิภาพออก>, slot=0x557cc2e606d8) ที่ ./build/../src/backend/executor/execTuples.c:930
#1 tts_buffer_heap_getsomeattrs (slot=0x557cc2e606d8, natts=5) ที่ ./build/../src/backend/executor/execTuples.c:695
#2 0x0000557cc1d3998c ใน slot_getsomeattrs_int (slot=slot@entry=0x557cc2e606d8, attnum=5) ที่ ./build/../src/backend/executor/execTuples.c:1912
#3 0x0000557cc1d28fba ใน slot_getsomeattrs (attnum=<เพิ่มประสิทธิภาพออก>, slot=0x557cc2e606d8) ที่ ./build/../src/include/executor/tuptable.h:344
#4 ExecInterpExpr (state=0x557cc2e620a8, econtext=0x557cc2ea1768, isnull=<optimized out>) ที่ ./build/../src/backend/executor/execExprInterp.c:482
#5 0x0000557cc1d5548d ใน ExecEvalExprSwitchContext (isNull=0x7ffdd2599507, econtext=0x557cc2ea1768, state=0x557cc2e620a8) ที่ ./build/../src/include/executor/executor.h:322
#6 ExecQual (econtext=0x557cc2ea1768, state=0x557cc2e620a8) ที่ ./build/../src/include/executor/executor.h:391
#7 MJFillInner (node=0x557cc2ea1558) ที่ ./build/../src/backend/executor/nodeMergejoin.c:494
#8 0x0000557cc1d55ce8 ใน ExecMergeJoin (pstate=0x557cc2ea1558) ที่ ./build/../src/backend/executor/nodeMergejoin.c:1353
#9 0x0000557cc1d2cc83 ใน ExecProcNode (node=0x557cc2ea1558) ที่ ./build/../src/include/executor/executor.h:248
#10 ExecutePlan (execute_once=<เพิ่มประสิทธิภาพออก>, ปลายทาง=0x557cc2e1a630, ทิศทาง=<เพิ่มประสิทธิภาพออก>, numberTuples=0, sendTuples=<เพิ่มประสิทธิภาพออก>, operation=CMD_SELECT, use_parallel_mode=<เพิ่มประสิทธิภาพออก>, planstate=0x557cc2ea1558, 
    เอสเตท=0x557cc2ea12f8) ที่ ./build/../src/backend/executor/execMain.c:1632
#11 standard_ExecutorRun (queryDesc=0x557cc2e1a5a0, ทิศทาง=<เพิ่มประสิทธิภาพออก>, จำนวน=0, execute_once=<เพิ่มประสิทธิภาพออก>) ที่ ./build/../src/backend/executor/execMain.c:350
#12 0x00007f0ec05ae09d ใน pgss_ExecutorRun (queryDesc=0x557cc2e1a5a0, direction=ForwardScanDirection, count=0, execute_once=<optimized out>) ที่ ./build/../contrib/pg_stat_statements/pg_stat_statements.c:1045
#13 0x0000557cc1cdbcd4 ใน PersistHoldablePortal (portal=portal@entry=0x557cc2d44b78) ที่ ./build/../src/backend/commands/portalcmds.c:407
#14 0x0000557cc1ff95f9 ใน HoldPortal (portal=portal@entry=0x557cc2d44b78) ที่ ./build/../src/backend/utils/mmgr/portalmem.c:642
#15 0x0000557cc1ff9e7d ใน PreCommit_Portals (isPrepare=isPrepare@entry=false) ที่ ./build/../src/backend/utils/mmgr/portalmem.c:738
#16 0x0000557cc1c001c4 ใน CommitTransaction () ที่ ./build/../src/backend/access/transam/xact.c:2087
#17 0x0000557cc1c015d5 ใน CommitTransactionCommand () ที่ ./build/../src/backend/access/transam/xact.c:3085
#18 0x0000557cc1ea211d ใน Finish_xact_command () ที่ ./build/../src/backend/tcop/postgres.c:2662
#19 0x0000557cc1ea4703 ใน exec_simple_query (query_string=0x557cc2c9cd28 "COMMIT") ที่ ./build/../src/backend/tcop/postgres.c:1264
#20 0x0000557cc1ea6143 ใน PostgresMain (argc=<optimized out>, argv=argv@entry=0x557cc2cf6c68, dbname=<optimized out>, username=<optimized out>) ที่ ./build/../src/backend/tcop/postgres .c:4339
#21 0x0000557cc1e25bcd ใน BackendRun (พอร์ต=0x557cc2ce94d0, พอร์ต=0x557cc2ce94d0) ที่ ./build/../src/backend/postmaster/postmaster.c:4526
#22 BackendStartup (พอร์ต=0x557cc2ce94d0) ที่ ./build/../src/backend/postmaster/postmaster.c:4210
#23 ServerLoop () ที่ ./build/../src/backend/postmaster/postmaster.c:1739
#24 0x0000557cc1e26b41 ใน PostmasterMain (argc=5, argv=<optimized out>) ที่ ./build/../src/backend/postmaster/postmaster.c:1412
#25 0x0000557cc1b70f4f ใน main (argc=5, argv=0x557cc2c96c30) ที่ ./build/../src/backend/main/main.c:210

การเพิ่ม log_statement = 'ทั้งหมด' ถึง /etc/postgresql/13/main/postgresql.conf ไม่ช่วยอะไรจริงๆ เช่น นายไปรษณีย์ ยุติกระบวนการทั้งหมดทันทีและแบบสอบถามจะไม่ถูกเขียนลงในบันทึก

นี่ สเตรส เอาต์พุตหลังจากรัน ให้สัญญา

[pid 20006] pwrite64(29, "COMMIT", 6, 15936) = 6
[pid 20006] pwrite64(29, "\0", 1, 15942) = 1
[pid 20006] ปิด (29) = 0
[pid 20006] --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x10} ---
[pid 20006] +++ ถูกฆ่าโดย SIGSEGV (ทิ้งคอร์) +++
<...เลือกดำเนินการต่อ> ) = ? ERESTARTNOHAND (จะเริ่มต้นใหม่หากไม่มีตัวจัดการ)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_DUMPED, si_pid=20006, si_uid=108, si_status=SIGSEGV, si_utime=0, si_stime=0} ---
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGSEGV && WCOREDUMP(s)}], WNOHANG, NULL) = 20006
เขียน(2, "2021-09-08 13:38:51.853 UTC [299"..., 198) = 198
เขียน(2, "2021-09-08 13:38:51.853 UTC [299"..., 88) = 88
ฆ่า (19324, SIGQUIT) = 0
ฆ่า (-19324, SIGQUIT) = 0
ฆ่า (19331, SIGQUIT) = 0
ฆ่า (-19331, SIGQUIT) = 0
ฆ่า (19320, SIGQUIT) = 0
ฆ่า (-19320, SIGQUIT) = 0
ฆ่า (19319, SIGQUIT) = 0
ฆ่า (-19319, SIGQUIT) = 0
ฆ่า (19321, SIGQUIT) = 0
ฆ่า (-19321, SIGQUIT) = 0
ฆ่า (19322, SIGQUIT) = 0
ฆ่า (-19322, SIGQUIT) = 0
ฆ่า (19323, SIGQUIT) = 0
ฆ่า (-19323, SIGQUIT) = 0
รอ 4(-1, 0x7ffe90814374, WNOHANG, NULL) = 0
rt_sigreturn({mask=[]}) = -1 EINTR (การเรียกระบบขัดจังหวะ)
rt_sigprocmask(SIG_SETMASK, ~[ILL TRAP ABRT BUS FPE SEGV CONT SYS RTMIN RT_1], NULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
เลือก(7, [5 6], NULL, NULL, {tv_sec=5, tv_usec=0}) = ? ERESTARTNOHAND (จะเริ่มต้นใหม่หากไม่มีตัวจัดการ)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=19320, si_uid=108, si_status=2, si_utime=14, si_stime=3} ---

มีวิธีติดตามการสืบค้น SQL ที่แน่นอนที่ถูกเรียกใช้หรือไม่

Michael Hampton avatar
cz flag
หากยังคงเกิดขึ้นที่จุดเดิม แสดงว่าคุณน่าจะพบข้อบกพร่องบางประเภทและควรส่งรายงานข้อบกพร่อง
cn flag
นอกเหนือจากข้างต้น คุณเคยดูบันทึกหรือไม่?
ng flag
@MichaelHampton ใช่ ฉันจะพยายามทำอย่างนั้น ในระหว่างนี้ ฉันต้องหาวิธีแก้ไขบางอย่างเพื่อหลีกเลี่ยงไม่ให้ postgres ขัดข้อง
ng flag
@NasirRiley ไม่มีอะไรน่าสนใจในบันทึกยกเว้นบรรทัดที่แสดงไปแล้ว
Score:2
ธง ng

ก่อนอื่นให้ติดตั้งสัญลักษณ์การดีบักสำหรับการแจกจ่ายของคุณ สำหรับ Debian distros:

ฉลาดติดตั้ง gdb postgresql-13-dbgsym

ข้ามไปยังเฟรมที่มีบางส่วน แบบสอบถามรายละเอียด ตัวแปร เช่น 12:

(gdb) เฟรม 12
#12 0x00007f0ec05ae09d ใน pgss_ExecutorRun (queryDesc=0x557cc302b7d0, direction=ForwardScanDirection, count=0, execute_once=<optimized out>) ที่ ./build/../contrib/pg_stat_statements/pg_stat_statements.c:1045
1,045 ใน ./build/../contrib/pg_stat_statements/pg_stat_statements.c

พิมพ์ตัวแปรนั้น:

(gdb) p แบบสอบถามรายละเอียด
$1 = (QueryDesc *) 0x557cc302b7d0

ตอนนี้คัดลอกบรรทัดด้านบนหลังจากเครื่องหมายเท่ากับและอ้างอิงโดยใช้ *

(gdb) พี *(QueryDesc *) 0x557cc302b7d0
$6 = {การดำเนินการ = CMD_SELECT, planningstmt = 0x557cc300e218, 
  sourceText = 0x557cc302b370 "\n", ' ' <ซ้ำ 12 ครั้ง>, "ประกาศ \"categoryPagePhotoUrl_image_urls\" เคอร์เซอร์โดยกดค้างไว้เพื่อ\n", ' ' <ซ้ำ 12 ครั้ง>, "เลือก di.itemId, image_number, ชื่อไฟล์ FROM ( SELECT *\n", ' ' <ซ้ำ 12 ครั้ง>, "จาก downl"..., snapshot = 0x557cc2e9b188, crosscheck_snapshot = 0x0, dest = 0x557cc302b860, params = 0x0, queryEnv = 0x0, instrument_options = 0, tupDesc ​​= 0x557cc2f7bff8, 
  เอสเตท = 0x557cc2cf8d08, planstate = 0x557cc2cf8f68, แล้ว_ดำเนินการ = จริง, เวลาทั้งหมด = 0x0}

มันไม่ได้ให้แบบสอบถามทั้งหมดแก่คุณ แต่อย่างน้อยก็มีแนวคิดว่าตารางใดที่เรียกใช้แบบสอบถาม

ขึ้นอยู่กับ จีดีบี เอาต์พุต ฉันจัดการเพื่อแยกไคลเอนต์ที่กำลังดำเนินการค้นหาดังกล่าว

ฉันได้ลองวิ่งแล้ว สูญญากาศเต็ม บนตารางที่ได้รับผลกระทบ, สร้างตารางและดัชนีใหม่, เปลี่ยนเป็นแบบจำลอง, คัดลอกฐานข้อมูลทั้งหมดโดยใช้ pg_dump. อย่างไรก็ตาม ปัญหายังคงมีอยู่บนสำเนาฐานข้อมูลด้วย

ในที่สุดฉันก็แยกเชื้อ a ได้ รหัส SQL ขั้นต่ำเพื่อทำซ้ำปัญหา.

$pg_createcluster 13 หลัก
$ สร้างb testdb
$ psql -d testdb -f postgresql-segfault.sql
สร้างสคีมา
สร้างตาราง
สำเนา 1
เปลี่ยนตาราง
เริ่ม
สร้างตาราง
ประกาศเคอร์เซอร์
 รหัสรายการ  
---------
 1190300
(1 แถว)

psql:postgresql-segfault:34: เซิร์ฟเวอร์ปิดการเชื่อมต่อโดยไม่คาดคิด
        นี่อาจหมายถึงเซิร์ฟเวอร์หยุดทำงานอย่างผิดปกติ
        ก่อนหรือขณะดำเนินการตามคำขอ
psql:postgresql-segfault:34: ร้ายแรง: การเชื่อมต่อกับเซิร์ฟเวอร์ขาดหายไป

ด้วยรหัสเพื่อทำซ้ำนี้ก็เพียงพอแล้ว รายงานความผิดพลาด ถึง pgsql-ข้อบกพร่อง รายชื่อผู้รับจดหมาย (มีเว็บฟอร์มด้วย) กลายเป็นจุดบกพร่องที่มีการดำเนินการซ้ำของแผนที่บรรลุผลสำเร็จแล้วบนเคอร์เซอร์ที่ไม่เสถียร ถูกรวมอยู่ใน PostgreSQL 13.4, 12.8 (และอาจเป็นเวอร์ชันอื่นๆ)

Miles avatar
kr flag
คุณช่วยฉันแก้ปัญหาได้มากในการดีบักอันนี้ ขอบคุณ

โพสต์คำตอบ

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