จะเกิดอะไรขึ้นถ้าคุณไม่ทำธุรกรรมกับฐานข้อมูล (เช่น SQL Server)


108

สมมติว่าฉันมีคำถาม:

begin tran
-- some other sql code

แล้วฉันก็ลืมที่จะกระทำหรือย้อนกลับไป

หากลูกค้ารายอื่นพยายามเรียกใช้แบบสอบถามจะเกิดอะไรขึ้น?

คำตอบ:


148

ตราบเท่าที่คุณไม่ได้ทำการCOMMITหรือROLLBACKการทำธุรกรรมมันยังคง "ทำงาน" และอาจมีการล็อก

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


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

12
หมายเหตุด้านข้าง: หากใช้ Management Studio การปิดหน้าต่างแบบสอบถามจะปิดการเชื่อมต่อ
Joe Phillips

3
@BradleyDotNET: ใช่แน่นอน
marc_s

2
โปรดทราบว่า SQL Server Management Studio จะยอมรับโดยอัตโนมัติหากคุณปิดหน้าต่างแบบสอบถาม / การเชื่อมต่อโดยค่าเริ่มต้น
Nuno

1
โปรดทราบว่าเมื่อไคลเอนต์ปิดการเชื่อมต่อในขณะที่ธุรกรรมกำลังทำงานอยู่จะไม่มีการย้อนกลับเสมอไปซึ่งขึ้นอยู่กับไคลเอ็นต์และฐานข้อมูล เช่นเมื่อแอป Java ปิดการเชื่อมต่อกับ Oracle db การเชื่อมต่อที่เปิดอยู่จะถูกคอมมิตโดยอัตโนมัติ
AviD

38

คุณสามารถลองทำด้วยตัวเองได้ซึ่งจะช่วยให้คุณรู้สึกได้ถึงวิธีการทำงานนี้

เปิดสองหน้าต่าง (แท็บ) ในสตูดิโอการจัดการแต่ละหน้าต่างจะมีการเชื่อมต่อกับ sql ของตัวเอง

ตอนนี้คุณสามารถเริ่มต้นธุรกรรมในหน้าต่างเดียวทำบางอย่างเช่นแทรก / อัปเดต / ลบ แต่ยังไม่ได้กระทำ จากนั้นในหน้าต่างอื่นคุณจะเห็นว่าฐานข้อมูลมีลักษณะอย่างไรจากภายนอกธุรกรรม ขึ้นอยู่กับระดับการแยกตารางอาจถูกล็อคจนกว่าหน้าต่างแรกจะถูกคอมมิตหรือคุณอาจ (ไม่) เห็นว่าธุรกรรมอื่น ๆ ทำอะไรไปแล้ว ฯลฯ

เล่นกับระดับการแยกที่แตกต่างกันและไม่มีคำใบ้ล็อคเพื่อดูว่าพวกเขามีผลต่อผลลัพธ์อย่างไร

และดูว่าเกิดอะไรขึ้นเมื่อคุณเกิดข้อผิดพลาดในการทำธุรกรรม

สิ่งสำคัญมากที่จะต้องเข้าใจว่าสิ่งเหล่านี้ทำงานอย่างไรหรือคุณจะนิ่งงันกับสิ่งที่ sql ทำหลาย ๆ ครั้ง

มีความสุข! GJ.


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

16

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

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


นั่นคือสิ่งที่ควรจะเป็น แต่ก็ไม่ได้เป็นเช่นนั้นเสมอไป
FalcoGer

... เช่น MySAM ของ mySQL ซึ่งไม่รองรับธุรกรรมนั่นเอง
Piskvor ออกจากอาคาร

3

ขึ้นอยู่กับระดับการแยกของธุรกรรมที่เข้ามา

อธิบายการแยกธุรกรรม SQL


6
ลักษณะการทำงานของธุรกรรมไม่ได้ขึ้นอยู่กับระดับการแยก จำนวนล็อคที่อาจทำให้เกิดขึ้น
marc_s

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

2

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


1

ตัวอย่างการทำธุรกรรม

เริ่มต้น tran tt

คำสั่ง sql ของคุณ

หากเกิดข้อผิดพลาดย้อนกลับ tran tt else กระทำ tran tt

ตราบเท่าที่คุณยังไม่ได้ดำเนินการกระทำ tran tt ข้อมูลจะไม่ถูกเปลี่ยนแปลง


1
โปรดทราบว่าการตั้งชื่อธุรกรรมไม่เพียง แต่ไม่จำเป็นใน MS SQL เท่านั้น แต่ยังสามารถให้ความรู้สึกที่ผิดพลาดในการควบคุม BEGIN TRAN X ... BEGIN TRAN Y ... ROLLBACK Yไม่ทำงานเช่น ดูstackoverflow.com/questions/1273376/…

0

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

คุณสามารถใช้dbcc opentranเพื่อดูรายละเอียดของธุรกรรมที่เปิดเก่าที่สุด


0

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


-4

ไม่ได้กำหนดลักษณะการทำงานดังนั้นคุณต้องตั้งค่าคอมมิตหรือการย้อนกลับอย่างชัดเจน:

http://docs.oracle.com/cd/B10500_01/java.920/a96654/basic.htm#1003303

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

Hsqldb ทำการย้อนกลับ

con.setAutoCommit(false);
stmt.executeUpdate("insert into USER values ('" +  insertedUserId + "','Anton','Alaf')");
con.close();

ผลลัพธ์คือ

2011-11-14 14: 20: 22,519 ข้อมูลหลัก [SqlAutoCommitExample: 55] [เปิดใช้งาน AutoCommit = false] 2011-11-14 14: 20: 22,546 ข้อมูลหลัก [SqlAutoCommitExample: 65] [พบ 0 # ผู้ใช้ในฐานข้อมูล]


2
นี่อาจเป็นจริงสำหรับ Oracle (ฉันไม่รู้) แต่ผู้ถามกำลังถามเกี่ยวกับ MS-SQL
PaulG

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