Kodokon kodokon.com

المعاملات: BEGIN، COMMIT، ROLLBACK وACID

اجعل عمليات الكتابة لديك ذرّية باستخدام المعاملات، وافهم ما تعنيه ضمانات ACID في الممارسة اليومية.

8 دقيقة · 3 أسئلة

افتح هذا الدرس في Kodokon

التحويل المصرفي هو تعليمتا UPDATE: خصم من حساب، وإضافة إلى الآخر. فإذا فشلت الثانية، تكذب قاعدة البيانات. إن المعاملة تجعل الكتلة غير قابلة للتجزئة، مع ضمانات ACID: A الذرّية (الكل أو لا شيء)، وC الاتساق (تبقى القيود صالحة)، وI العزل (لا ترى المعاملات المتزامنة بعضها منجزًا جزئيًا أبدًا)، وD الديمومة (تصمد عملية COMMIT أمام الأعطال). لهذا الدرس، فضّل عميل sqlite3 الحقيقي: فبعض بيئات الويب التجريبية تؤكّد كل استعلام تلقائيًا.

SQL
CREATE TABLE accounts (
  id INTEGER PRIMARY KEY,
  owner TEXT NOT NULL,
  balance REAL NOT NULL CHECK (balance >= 0)
);

INSERT INTO accounts (owner, balance)
VALUES
  ('alice', 500.0),
  ('bruno', 120.0);
يمنع قيد CHECK أي رصيد سالب.

الحالة الاسمية: تفتح BEGIN المعاملة، وتتراكم عمليات الكتابة، وتجعلها COMMIT نهائية دفعة واحدة. وفي ما بينهما، لا يرى أي اتصال آخر الحالة الوسيطة (خُصم من alice، ولم يُضَف إلى bruno بعد).

SQL
BEGIN;

UPDATE accounts
SET balance = balance - 200
WHERE owner = 'alice';

UPDATE accounts
SET balance = balance + 200
WHERE owner = 'bruno';

COMMIT;

SELECT owner, balance FROM accounts;
تحويل ذرّي: 300 لـ alice، و320 لـ bruno.

والآن حالة الفشل. إن خصم 400 من bruno سينتهك CHECK (balance >= 0): فتفشل التعليمة. دقيقة في SQLite: افتراضيًا، يُلغي الخطأ التعليمة المخالفة لكنه يترك المعاملة مفتوحة. ويعود القرار إلى كود تطبيقك: ROLLBACK للتراجع عن كل شيء (وهو رد الفعل السليم)، أو المتابعة إذا كان الخطأ قابلًا للتدارك.

SQL
BEGIN;

UPDATE accounts
SET balance = balance - 400
WHERE owner = 'bruno';
-- Error: CHECK (balance >= 0) rejects the row.

ROLLBACK;

SELECT owner, balance FROM accounts;
بعد ROLLBACK، تبقى الأرصدة من آخر COMMIT سليمة.

اختبار المعرفة

تأكّد من أنك تذكّرت النقاط الأساسية في هذا الدرس.

  1. ماذا تضمن الذرّية، أي حرف A في ACID؟
    • تعمل استعلامات المعاملة بسرعة أكبر
    • تُطبَّق المعاملة بالكامل أو لا تُطبَّق إطلاقًا
    • لا يمكن لمعاملتين قراءة الجدول نفسه أبدًا
  2. بعد ROLLBACK، في أي حالة تكون قاعدة البيانات؟
    • حالة آخر COMMIT، وكأن BEGIN لم يحدث قط
    • تُحفظ تعليمات UPDATE التي نجحت قبل الخطأ
    • تبقى قاعدة البيانات مقفلة حتى BEGIN التالي
  3. لماذا تكون 10,000 تعليمة INSERT أسرع بكثير في معاملة SQLite واحدة؟
    • يضغط SQLite البيانات المُدرَجة دفعةً واحدة
    • مزامنة واحدة للقرص عند COMMIT بدلًا من واحدة لكل تعليمة
    • تُعطَّل الفهارس أثناء المعاملة