انتقال للمقال

مبادئ الـ ACID في إدارة الـ Transactions

السلام عليكم ورحمة الله وبركاته

وقت القراءة: ≈ 5 دقائق

المقدمة


هذه المقالة تعتبر مقدمة لأهم مبادئ قواعد البيانات وهي مبادئ الـ ACID الأربعة
والتي تعتبر من أهم المبادئ التي يجب على كل مطور أن يعرفها ويفهمها جيدًا

وهي كالتالي:

وهذه المبادئ هي التي تقوم عليها فكرة الـ Database Transactions
وهي تساعدنا على تنفيذ العمليات بشكل آمن ومضمون ودقيق

لكن ما هي الـ Transactions ؟
كيف يمكننا أن نشرح ونتعلم مبادئ شئ نحن نجهله من الأساس
لذا قبل أن نبدأ في شرح كل مبدأ على حدة سنتعرف على ما هي الـ Transactions أولًا

ما هي الـ Transactions ؟

الـ Transactions هي مجموعة من العمليات التي تتم بشكل متسلسل ومتتابع
والعمليات نقصد بها أي Query تقوم بتنفيذها على قاعدة البيانات

فمثلًا إذا قمت بإضافة مستخدم جديد إلى قاعدة البيانات ثم قمت بتعديل شيء ما وقمت في
عملية أخرى لتحذف شيء معين

INSERT INTO users (name, email) VALUES ('Ahmed', 'eltabaraniahmed@gmail');
UPDATE users SET name = 'Mohamed' WHERE id = 1;
DELETE FROM users WHERE id = 2;

كل عملية منفصلة هنا تسمى Query والعمليات الثلاثة مجتمعة نسميها Transaction

إذا نستطيع أن نقول أن الـ Transaction هي مجموعة من الـ Query التي تتم بشكل
متسلسل ومتتابع وغالبًا ما تكون مرتبطة ببعضها البعض وتحتاج لتنفيذها بترتيب معين
ومبادئ الـ ACID هي مبادئ وضعت لجعل الـ Transactions تنفذ بشكل صحيح دون أي مشاكل

كيفية كتابة Transaction

في معظم الـ SQL لكي تضع مجموعة من الـ Query في Transaction تقوم بكتابة
BEGIN ثم تبدأ بكتابة مجموعة الـ Query الخاصة بك ثم تنهي بـ COMMIT
وكلمة COMMIT تعني نهاية الـ Transaction وبالتالي سيتم تطبيق كل الـ Query
التي كتبتها داخل الـ Transaction على قاعدة البيانات

وإذا حدث أي خطأ في أي Query خلال الـ Transaction سيتم إلغاء الـ
Transaction بشكل تلقائي
وعملية إلغاء الـ Transaction تعرف بـ ROLLBACK أي تراجع عن كل ما سبق تنفيذه


ليس كل العمليات التي تنفذ بشكل متسلسل ومتتابع تعتبر Transaction
عليك أن تضعها داخل Transaction لكي تكون Transaction وتتمتع بكل خصائص الـ
ACID

وكل لغة SQL تقدم لك طريقة لكتابة Transaction وتنفيذها وسنرى هذا تاليًا

مثال عملي على Transaction

لنفترض أن لدينا جدول يسمى Accounts وجدول آخر يسمى Histories
ونريد تنفيذ عملية تحويل مبلغ من حساب إلى حساب آخر على سبيل المثال

ونريد تنفيذ هذه العمليات بدون Transaction لذا يمكننا كتابتها بدون Transaction كالتالي:

UPDATE Accounts SET balance = balance - 100 WHERE user_id = 1;
INSERT INTO Histories (user_id, amount) VALUES (1, -100);

UPDATE Accounts SET balance = balance + 100 WHERE user_id = 2;
INSERT INTO Histories (user_id, amount) VALUES (2, 100);

هكذا تخيل معي أنه تم تنفيذ الـ Query الأولى بنجاح والثانية بنجاح لكن عندما
وصلنا للـ Query الثالثة حدث خطأ ما
في هذه الحالة تم سحب المال من المستخدم رقم 1 وتم تسجيل العملية في جدول
Histories ولكن لم يتم إضافة المال للمستخدم رقم 2
وهذه مشكلة كبيرة

لكن لو كنا وضعنا هذه العمليات داخل Transaction فإن النتيجة ستكون مختلفة:

BEGIN;

UPDATE Accounts SET balance = balance - 100 WHERE user_id = 1;
INSERT INTO Histories (user_id, amount) VALUES (1, -100);

UPDATE Accounts SET balance = balance + 100 WHERE user_id = 2;
INSERT INTO Histories (user_id, amount) VALUES (2, 100);

COMMIT;

نفس الكود السابق ولكن هذه المرة قمنا بوضعه داخل Transaction عن طريق كتابة
BEGIN و COMMIT
وهذا يعني أنه إذا حدث أي خطأ في أي Query خلال الـ Transaction سيتم التراجع عن كل ما تم تنفيذه
بالتالي لو تم تنفيذ الـ Query الأولى والثانية بنجاح ولكن حدث خطأ في الـ
Query الثالثة فسيتم التراجع عن كل شيء تم تنفيذه ولن يتم تطبيق أي شيء على قاعدة البيانات

هذا يعني أنه إذا حدث أي خطأ في أي Query خلال الـ Transaction سيتم التراجع عن كل ما تم تنفيذه ولن يتم تطبيق أي شيء على قاعدة البيانات

لماذا نحتاج مبادئ الـ ACID ؟

الـ Transaction يحقق لك مبادئ الـ ACID لأنه تم بناءه عليها وبالتالي
هو يتبع هذه المبادئ بشكل تلقائي
وهذا ما يجعل الـ Transactions تعمل بشكل صحيح وبدون أي مشاكل

لكن يبقى السؤال ما هي مبادئ الـ ACID بالتحديد ؟
أظن أننا قد تكلمنا عن الـ Transactions وكيف هي تحقق بمبادئ الـ ACID ولكن لم
نتكلم عن كل مبدأ على حدة

ولا أريدك أن تظن أن الـ Transactions هي مجرد مجموعة من الـ Query لا أكثر ولا
أقل
لذا سنتعرف على كل مبدأ على حدة ونتعرف على فائدته وما الذي يقدمه في الـ
Transaction وكيف يساعدنا على تفادي المشاكل


حسنًا كما قلنا فأن هناك أربعة مبادئ أساسية للـ Transactions وهي مبادئ الـ
ACID
وهذه المبادئ هي التي تجعل الـ Transactions تعمل بشكل صحيح بدون أي مشاكل
لذا لكي نفهم الـ Transactions جيدًا علينا أن نتعرف على هذه المبادئ التي بنيت
عليها

  • مبدأ الـ Atomicity يضمن أن الـ Transaction تنفذ بالكامل أو لا تنفذ على الإطلاق
  • مبدأ الـ Consistency يضمن أن البيانات تبقى متناسقة ومتوافقة مع القيود
  • مبدأ الـ Isolation يضمن أن كل Transaction معزولة عن الأخرى
  • مبدأ الـ Durability يضمن أن البيانات المحفوظة لن تُفقد حتى عند الأعطال

ختامًا

في المقالات المرفقة شرحنا مبادئ الـ ACID وكيفية تطبيقها في الـ Database
وكيفية تحقيق كل مبدأ من هذه المبادئ وكيفية تطبيقها عمليًا
بعض المقالات قد تكون طويلة بعض الشيء لكن كنت أريد أن أشرح كل شيء بشكل عملي مع أمثلة واقعية على قدر المستطاع

وحلولها بإستخدام Laravel وبالطبع شرحت باستخدام الـ ORM الذي يقدمه لأنني أردت
التركيز على الأمثلة العملية التي ستقابلها في العمل
وأنت في الغالب ستتعامل مع الـ Database عن طريق الـ ORM وليس الـ SQL بشكل
مباشر


ملخص المقالات

أولًا تكلمنا عن الـ Transaction وكيف أنها عبارة عن مجموعة من الـ Query التي
تعمل معًا وتنفذ معًا
وكيف أنها تحقق لك المباديء الأربعة للـ ACID بما في ذلك Atomicity
وConsistency وIsolation وDurability
وتضمن لك أن الـ Transaction ستنفذ بنجاح وستحفظ البيانات بشكل صحيح

ثم انتقلنا لمبدأ الـ Atomicity والذي يمكننا أن نختصره بجملة واحدة وهي أن الـ
Transaction يجب أن تنفذ بالكامل أو لا تنفذ على الإطلاق
بالتالي إذا حدث أي خطأ في الـ Transaction فإنه يجب عليك إلغاء كل التعديلات
التي تمت ROLLBACK وإعادة البيانات إلى حالتها الأولى وكأن شيء لم يحدث

ثم تحدثنا عن مبدأ الـ Consistency وهو مفهوم نظري واسع جدًا والذي يضمن لك أن
البيانات ستكون دائمًا في حالة صحيحة ومتسقة
ويضمن أن الـ Transaction تلتزم بالـ Constraints الذي وضعتها على البيانات ولا
تخالفها
بالتالي ستحترم على سبيل المثال الـ Foreign Key والـ Unique Key والـ Check
والـ Default والـ Not Null وغيرها
ومفهوم الـ Consistency مفهوم واسع ويتطرق للعديد من الأمور سواء على مستوى
الأخطاء البشرية أو الأمور التي تحدث في الـ Database Distribution System وهل
هناك تناقضات بين البيانات في الـ Database المختلفة الموزعة في السيرفرات
المختلفة

ثم تحدثنا عن مبدأ الـ Isolation وهو مبدأ يحدد لك كيفية تعامل الـ Transaction
مع البيانات وكيفية عزل الـ Transaction عن بعضها البعض
والذي يقوم بمنع أي Query أو Transaction أخرى من الوصول إلى البيانات التي
تقوم بتعديلها
ويحتوى على عدة مستويات للعزل منها

  • Read Uncommitted: يسمح لأي Transaction بقراءة البيانات حتى لو لم يتم عمل COMMIT للبيانات
  • Read Committed: يمنع أي Transaction من قراءة البيانات حتى يتم عمل COMMIT للبيانات
  • Repeatable Read: يعزل الـ Transaction عن أي تغييرات خارجية تحدث في البيانات
  • Serializable: ينفذ الـ Transaction بشكل تسلسلي ويمنع أي Transaction من التداخل مع الـ Transaction الأخرى
  • Snapshot: يقوم بعمل نسخة زمنية من البيانات ويعمل على قراءة هذه النسخة وليس البيانات الحالية

يوجد مشاكل تحدث في حالة عدم تطبيق مبدأ الـ Isolation مثل

  • Dirty Read: القدرة على قراءة البيانات قبل عمل COMMIT لها
  • Non-Repeatable Read
  • Phantom Read
  • Lost Update

وأيضًا يمكنك تطبيق مبدأ الـ Isolation بعدة طرق منها

  • Pessimistic Lock
    • له نوعان مهمين وهما
      • Exclusive Lock
      • Shared Lock
  • Optimistic Lock
    • يقوم على فكرة وجود حقل version أو timestamp لتحقق منه بعد التعديل

ثم أنهينا بمبدأ الـ Durability والذي يضمن لك أن البيانات ستكون موجودة ولن تفقد
حتى في حالة حدوث عطل أو انقطاع مفاجئ في النظام
والذي يمكنك أن نخترصه بأنك عندما تقول لي أنك قمت بعمل COMMIT بأنك تضمن لي أن
البيانات قد تم حفظها بمعنى أن الرجل يلتزم بكلمته
والمبدأ مثله مثل الـ Consistency يعتبر مبدأ نظري ويخص بناء أنظمة قواعد
البيانات مثل MySQL و PostgreSQL وغيرها
ولكن يمكنك تحقيقه بنفسك عن طريق توفير نوع من الـ Backup لقاعدة البيانات الخاصة
بك

أتمنى أن تكون قد استفدت من هذه المقالات وأن تكون قد فهمت كل شيء بشكل جيد