ธุรกรรม
ยืนยันและย้อนกลับ
ธุรกรรม เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
ธุรกรรมคืออะไร
ธุรกรรมจะจัดกลุ่มการดำเนินการกับฐานข้อมูลหลายรายการให้เป็นหน่วยเดียวที่ต้องสำเร็จทั้งหมดหรือไม่สำเร็จเลย
คำสั่งทุกคำสั่งต้องทำงานสำเร็จและการเปลี่ยนแปลงถูกทำให้ถาวร (ยืนยันการเปลี่ยนแปลง) หรือหากมีสิ่งใดล้มเหลว การเปลี่ยนแปลงทั้งหมดจะถูกยกเลิก (ย้อนกลับ) วิธีนี้ช่วยให้ฐานข้อมูลยังคงสอดคล้องกัน
ACID ในหนึ่งนาที
ธุรกรรมมีการรับประกันตามหลัก ACID:
- ความเป็นอะตอม — สำเร็จทั้งหมดหรือไม่สำเร็จเลย
- ความสอดคล้อง — เปลี่ยนฐานข้อมูลจากสถานะที่ถูกต้องหนึ่งสถานะไปเป็นอีกสถานะที่ถูกต้อง
- การแยกออกจากกัน — ธุรกรรมที่ทำงานพร้อมกันจะไม่ทำให้ข้อมูลของกันและกันเสียหาย
- ความคงทน — เมื่อยืนยันการเปลี่ยนแปลงแล้ว การเปลี่ยนแปลงนั้นจะยังคงอยู่แม้ระบบขัดข้อง
โหมดการยืนยันอัตโนมัติ
โดยค่าเริ่มต้น การเชื่อมต่อของระบบเชื่อมต่อฐานข้อมูล Java จะทำงานในโหมดการยืนยันอัตโนมัติ: ทุกคำสั่งเป็นธุรกรรมของตัวเองและได้รับการยืนยันการเปลี่ยนแปลงทันที
วิธีนี้เหมาะกับคำสั่งเดียว แต่ใช้ไม่ได้เมื่อการเขียนข้อมูลหลายรายการต้องสำเร็จไปพร้อมกัน หากต้องการควบคุมธุรกรรมด้วยตนเอง ให้ปิดการยืนยันอัตโนมัติ
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/bank";
try (Connection conn = DriverManager.getConnection(url, "app", "secret")) {
System.out.println("Default auto-commit: " + conn.getAutoCommit());
conn.setAutoCommit(false);
System.out.println("Now manual: " + conn.getAutoCommit());
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}การยืนยันและการย้อนกลับ
เมื่อปิดการยืนยันอัตโนมัติแล้ว คุณจะเป็นผู้กำหนดขอบเขตเอง:
conn.commit()ทำให้การเปลี่ยนแปลงที่รอดำเนินการทั้งหมดเป็นการเปลี่ยนแปลงถาวรconn.rollback()ยกเลิกการเปลี่ยนแปลงเหล่านั้น
ตัวอย่างคลาสสิกคือการโอนเงิน: หักเงินจากบัญชีหนึ่งและเพิ่มเงินเข้าบัญชีอีกบัญชีหนึ่ง ทั้งสองรายการต้องเกิดขึ้นพร้อมกัน หรือไม่เกิดขึ้นเลย
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/bank";
String debit = "UPDATE account SET balance = balance - ? WHERE id = ?";
String credit = "UPDATE account SET balance = balance + ? WHERE id = ?";
try (Connection conn = DriverManager.getConnection(url, "app", "secret")) {
conn.setAutoCommit(false);
try (PreparedStatement d = conn.prepareStatement(debit);
PreparedStatement c = conn.prepareStatement(credit)) {
d.setInt(1, 100); d.setInt(2, 1); d.executeUpdate();
c.setInt(1, 100); c.setInt(2, 2); c.executeUpdate();
conn.commit();
System.out.println("Transfer committed");
} catch (SQLException ex) {
conn.rollback();
System.out.println("Rolled back: " + ex.getMessage());
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}รูปแบบการย้อนกลับเมื่อเกิดความล้มเหลว
โครงสร้างที่ควรจำมีดังนี้:
- ปิดการยืนยันอัตโนมัติ
- ทำงานภายใน
tryชั้นใน - เมื่อสำเร็จ ให้เรียก
commit() - ใน
catchให้เรียกrollback()แล้วส่งต่อข้อผิดพลาดเดิมหรือบันทึกลงระบบ
หากไม่ย้อนกลับ ความล้มเหลวอาจทำให้ฐานข้อมูลถูกปรับปรุงไปเพียงครึ่งเดียว
จำลองความเป็นอะตอม
นี่คือแนวคิดการทำงานแบบสำเร็จทั้งหมดหรือไม่สำเร็จเลย ซึ่งจำลองด้วย Java แบบเรียบง่ายเพื่อให้ทำงานได้โดยลำพัง เราใช้การปรับปรุงสองรายการกับภาพสถานะ หากรายการใดรายการหนึ่งล้มเหลว เราจะคืนค่าภาพสถานะนั้น
public class Main {
public static void main(String[] args) {
int[] balances = {500, 300};
int[] backup = balances.clone();
try {
balances[0] -= 200;
if (balances[0] < 0) throw new IllegalStateException("insufficient funds");
balances[1] += 200;
System.out.println("Commit: " + balances[0] + ", " + balances[1]);
} catch (RuntimeException e) {
balances = backup;
System.out.println("Rollback: " + balances[0] + ", " + balances[1]);
}
}
}จุดบันทึก
จุดบันทึกคือตัวทำเครื่องหมายภายในธุรกรรม คุณสามารถย้อนกลับไปยังจุดนั้นได้โดยไม่ต้องยกเลิกธุรกรรมทั้งหมด
Savepoint sp = conn.setSavepoint()conn.rollback(sp)จะยกเลิกเฉพาะงานที่เกิดขึ้นหลังจุดนั้น
มีประโยชน์สำหรับการกู้คืนบางส่วนในธุรกรรมที่ใช้เวลานาน
ระดับการแยกธุรกรรม
การแยกธุรกรรมจะควบคุมว่าธุรกรรมหนึ่งมองเห็นงานที่ยังไม่ได้ยืนยันการเปลี่ยนแปลงของอีกธุรกรรมหนึ่งได้มากน้อยเพียงใด ระบบเชื่อมต่อฐานข้อมูล Java กำหนดระดับผ่าน conn.setTransactionIsolation(...):
TRANSACTION_READ_COMMITTED— ค่าเริ่มต้นที่ใช้กันทั่วไปTRANSACTION_REPEATABLE_READTRANSACTION_SERIALIZABLE— แข็งแกร่งที่สุดและช้าที่สุด
การแยกธุรกรรมในระดับสูงช่วยป้องกันความผิดปกติ แต่ลดการทำงานพร้อมกัน
ความผิดปกติในการอ่าน
การแยกธุรกรรมในระดับต่ำอาจทำให้เกิดสิ่งต่อไปนี้:
- การอ่านข้อมูลสกปรก — มองเห็นการเปลี่ยนแปลงที่อีกธุรกรรมหนึ่งยังไม่ได้ยืนยัน
- การอ่านซ้ำไม่ได้ — แถวข้อมูลเปลี่ยนแปลงระหว่างการอ่านสองครั้ง
- การอ่านข้อมูลแฝง — มีแถวข้อมูลใหม่ปรากฏขึ้นและตรงกับคำค้นหาก่อนหน้า
เลือกระดับต่ำที่สุดที่ยังป้องกันความผิดปกติซึ่งตรรกะของคุณยอมรับไม่ได้
คืนค่าการยืนยันอัตโนมัติ
หากคุณยืมการเชื่อมต่อมาจากพูล ให้คืนค่าเดิมก่อนส่งการเชื่อมต่อนั้นกลับไป
หลังจากทำธุรกรรมด้วยตนเองแล้ว ให้เรียก conn.setAutoCommit(true) อีกครั้ง (หรือคืนค่าเป็นค่าที่ตรวจพบขณะยืม) เพื่อไม่ให้ผู้ใช้คนถัดไปประหลาดใจกับการตั้งค่าของคุณ
ทำธุรกรรมให้สั้น
ธุรกรรมจะถือล็อกไว้จนกว่าจะยืนยันการเปลี่ยนแปลงหรือย้อนกลับ ธุรกรรมที่ใช้เวลานานจะขัดขวางงานอื่นและเพิ่มความเสี่ยงต่อภาวะชะงักงัน
- อย่าดำเนินการติดต่อเครือข่ายที่ช้าหรือรอการป้อนข้อมูลจากผู้ใช้ภายในธุรกรรมที่เปิดอยู่
- รวบรวมข้อมูลให้เสร็จก่อน จากนั้นจึงเปิดการเชื่อมต่อ เขียนข้อมูล และยืนยันการเปลี่ยนแปลงอย่างรวดเร็ว
ธุรกรรมที่สั้นและมุ่งเน้นเฉพาะงานจะรองรับการขยายระบบได้ดีกว่ามาก
ตรวจสอบอย่างรวดเร็ว
การเรียก connection.rollback() มีผลอย่างไร
สรุปทบทวน
ธุรกรรมช่วยให้คุณมั่นใจในความปลอดภัยแบบสำเร็จทั้งหมดหรือไม่สำเร็จเลย:
- ปิดการยืนยันอัตโนมัติด้วย
setAutoCommit(false) - เรียก
commit()เมื่อสำเร็จ และเรียกrollback()เมื่อเกิดความล้มเหลว - ใช้จุดบันทึกสำหรับการย้อนกลับบางส่วน
- ปรับระดับการแยกธุรกรรมเพื่อสร้างสมดุลระหว่างความถูกต้องและการทำงานพร้อมกัน
- คืนค่าการยืนยันอัตโนมัติก่อนส่งการเชื่อมต่อในพูลกลับไป
คำถามที่พบบ่อย
บทเรียน “ธุรกรรม” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ธุรกรรม” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ธุรกรรม”
ยืนยันและย้อนกลับ คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “ธุรกรรม” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม
ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ