แสดงธุรกรรมที่เปิดใน MySQL


99

ฉันทำแบบสอบถามโดยไม่มีข้อผูกมัด จากนั้นแอปพลิเคชันก็หยุดลง

ฉันจะแสดงธุรกรรมที่เปิดอยู่เหล่านี้และกระทำหรือยกเลิกได้อย่างไร


ฉันคิดว่าธุรกรรมทั้งหมดของคุณจะถูกยกเลิกเมื่อตัดการเชื่อมต่อ แต่ก็ไม่แน่ใจ 100%
โยฮัน

คุณใช้ตารางประเภทใด MyISAM, InnoDB ฯลฯ ?
cdeszaq

@cdeszaq เห็นได้ชัดว่าไม่ใช่ MyISAM ไม่มีธุรกรรมนอกจากคำถามที่ไม่มีส่วนเกี่ยวข้องกับตารางจริงๆ
โยฮัน

2
@ โจฮัน - ฉันให้ MyISAM เป็นตัวอย่างของตารางเท่านั้น และมันก็เป็นอย่างมากไม่ว่าเพราะไม่ได้ตารางทั้งหมดที่สนับสนุนการทำธุรกรรมในลักษณะเดียวกันในเรื่องเกี่ยวกับการทำธุรกรรมในการสูญเสียการเชื่อมต่อกับ
cdeszaq

@cdeszaq เอกสาร MySQL ระบุบางสิ่งที่แตกต่างกันมาก
โยฮัน

คำตอบ:


63

ฉันจะแสดงธุรกรรมที่เปิดอยู่เหล่านี้และกระทำหรือยกเลิกได้อย่างไร

ไม่มีธุรกรรมที่เปิดอยู่ MySQL จะย้อนกลับธุรกรรมเมื่อตัดการเชื่อมต่อ
คุณไม่สามารถทำธุรกรรม (IFAIK) ได้

คุณแสดงเธรดโดยใช้

SHOW FULL PROCESSLIST  

ดู: http://dev.mysql.com/doc/refman/5.1/th/thread-information.html

มันจะไม่ช่วยคุณเพราะคุณไม่สามารถทำธุรกรรมจากการเชื่อมต่อที่ขาด

จะเกิดอะไรขึ้นเมื่อการเชื่อมต่อขาด
จากเอกสาร MySQL: http://dev.mysql.com/doc/refman/5.0/en/mysql-tips.html

4.5.1.6.3 ปิดการใช้งาน mysql Auto-Reconnect

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

พฤติกรรมนี้อาจเป็นอันตรายสำหรับคุณดังตัวอย่างต่อไปนี้ที่เซิร์ฟเวอร์ถูกปิดและรีสตาร์ทระหว่างคำสั่งที่หนึ่งและสองโดยที่คุณไม่รู้ตัว:

ดูเพิ่มเติมที่: http://dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html

วิธีวินิจฉัยและแก้ไขใน
การตรวจสอบการเชื่อมต่ออัตโนมัติ:

หากเกิดการเชื่อมต่อใหม่โดยอัตโนมัติ (ตัวอย่างเช่นจากการเรียก mysql_ping ()) จะไม่มีการระบุอย่างชัดเจน ในการตรวจสอบการเชื่อมต่อใหม่ให้โทรmysql_thread_id()เพื่อรับตัวระบุการเชื่อมต่อเดิมก่อนโทรmysql_ping()จากนั้นโทรmysql_thread_id()อีกครั้งเพื่อดูว่าตัวระบุมีการเปลี่ยนแปลงหรือไม่

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


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

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

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

@alex เอกสารอย่างเป็นทางการระบุว่านั่นคือพฤติกรรมที่บันทึกไว้ ดูลิงก์
โยฮัน

สวยจังโยฮัน ตอบคำถามและแสดงผลลัพธ์บางอย่างและแนวทางแก้ไขผลที่ตามมาทั้งหมดนี้ภายในไม่กี่ย่อหน้า
เจอราร์ด

55

แม้ว่าในกรณีนี้จะไม่มีธุรกรรมเหลืออยู่ตามที่ @Johan กล่าว แต่คุณสามารถดูรายการธุรกรรมปัจจุบันใน InnoDB พร้อมข้อความค้นหาด้านล่างได้หากต้องการ

SELECT * FROM information_schema.innodb_trx\G

จากเอกสาร :

ตาราง INNODB_TRX ประกอบด้วยข้อมูลเกี่ยวกับทุกธุรกรรม (ไม่รวมธุรกรรมแบบอ่านอย่างเดียว) ที่กำลังดำเนินการภายใน InnoDB รวมถึงว่าธุรกรรมกำลังรอการล็อกหรือไม่เมื่อธุรกรรมเริ่มต้นขึ้นและคำสั่ง SQL ที่ธุรกรรมกำลังดำเนินการอยู่หากมี


อย่าคิดว่ามีวิธีใดที่จะบอกได้ว่าธุรกรรมในตารางนั้นเป็นของคำขอ / เซสชันเฉพาะของคุณหรือไม่?
Captain Hypertext

1
โปรดทราบว่า\Gตัวปรับแต่งในตอนท้ายมีประโยชน์เฉพาะในกรณีที่คุณต้องการจัดรูปแบบผลลัพธ์แบบสอบถามภายในเครื่องมือ mysql CLI หากคุณใช้เครื่องมือ GUI เช่น Mysql Workbench คุณไม่จำเป็นต้องใช้
barell

30

คุณสามารถใช้show innodb status(หรือshow engine innodb statusสำหรับ mysql เวอร์ชันใหม่กว่า) เพื่อรับรายการของการดำเนินการทั้งหมดที่รอดำเนินการอยู่ภายในโปรแกรม InnoDB ฝังอยู่ในผนังของผลลัพธ์จะเป็นธุรกรรมและรหัสกระบวนการภายในที่พวกเขากำลังทำงานอยู่

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

นี่คือสิ่งที่คุณต้องการค้นหา:

------------
TRANSACTIONS
------------
Trx id counter 0 140151
Purge done for trx's n:o < 0 134992 undo n:o < 0 0
History list length 10
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0 0, not started, process no 17004, OS thread id 140621902116624
MySQL thread id 10594, query id 10269885 localhost marc
show innodb status

ในกรณีนี้ตอนนี้มีการเชื่อมต่อกับเอ็นจิ้น InnoDB เพียงครั้งเดียว (การเข้าสู่ระบบของฉันเรียกใช้showแบบสอบถาม) ถ้าบรรทัดที่มีการเชื่อมต่อที่เกิดขึ้นจริง / kill 10594รายการติดที่คุณต้องการที่จะยุติแล้วคุณต้องการทำ


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

3
ดีกว่าที่จะฆ่าธุรกรรมที่ค้างอยู่โดยไม่ต้องรอให้หมดเวลาในการล้างข้อมูลคุณอาจเสี่ยงต่อการชะงักงัน
Marc B

ใช่ +1 สำหรับความคิดเห็นนั้น ลืมเรื่องการหยุดชะงักเหล่านั้นไปสักนาที
โยฮัน

@MarcB ทำไมพวกเขาถึงเปลี่ยนเป็นshow engine innodb status?
Pacerier

2

เมื่อใช้แบบสอบถามนี้คุณจะเห็นธุรกรรมที่เปิดอยู่ทั้งหมด

รายการทั้งหมด:

SHOW FULL PROCESSLIST  

หากคุณต้องการฆ่ารหัสธุรกรรมคัดลอกรายการแฮงและฆ่าธุรกรรมโดยใช้คำสั่งนี้:

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