پرش به مطلب اصلی

ACID

در ابتدا باید بگیم ترنزکشن چیه؟ ترنزکشن یک مجموعه کوئری که به صورت یه unit of work رفتار میکنه و نمیتونه split بشه. و ترنزکشن یه چرخه داره

  • Transaction begin(checkpoint)
  • Transaction commit(savepoint)
  • Transaction rollback
  • Transaction unexpected ending = rollback(Crash)

tx = transaction


Atomicity

این به معنیه که یا همه کار ها انجام میشه یا هیچ کدوم از تغیییرات اعمال نمیشه و اگر حتی یکی از عملیات های یک transaction شکست بخوره کل TX رول بک میشه. یا همه کوئری های داخل یک tx باید موفق باشه.

حالا ممکنه کوئری های ما درست باشه و یهو وسط یه کوئری دیتابیس کرش کنه. اون موقع دیگه ما مقصر نبودیم اصن که. دیتابیس باید بتونه بعد از زیستازت برگرده به حالت صحیح

lack of atomicity lead to weak consistency


Consistency

این ویژگی میگه بعد از انجام هر تراکنش دیتابیس از یک وضعیت معتبر به یک وضعیت معتبر دیگه میره. مثلا حساب به وضعیت منفی نمیره یا مثلا فیلد FK نباید به سطری که وجود ندارد اشاره کند

[[BASE#ا**Eventual consistency (سازگاری نهایی) **]]


Isolation

این ویژگی برای اینه که TX های ما باید بصورت stateless باشن و نباید روی هم تاثیر بزارن. مثلا اگر دوتا تراکنش بخواد موجودی حساب رو عوض کنن روی هم تاثیری نزارن و تداخلی پیش نیاد. یا به عبارتی دیگر ایا tx من میتونه تغییراتی که توسط tx های دیگر ایجاد شده ببینه؟

[[Isolation Level]]


Durability

پس از موفقیت آمیز بودن یک TX تغییرات باید روی ‌DB حتی در صورت بروز خطاهای سیستمی اعمال بشن(مثل قطع برق) به عبارتی دیگر اگر در جواب tx به من گفتی که commit شده دفعه بعدی هم که میام تو db هستش

  • دیتابیس ها معمولا اینکارو با کمک WAL = Write ahead log انجام میدن یعنی قبل از ایجاد هر تغییر در db ابتدا اون رو در فایل لاگ مینویسن. حالا ممکنه لاگ های ما که تو کش هستن به محض اینکه میخوان برن روی دیسک دیتابیس بترکه. اینجوری دیتابیس فکر میکنه ذخیره شده ولی هیچی ذخیره نشده. اینجا ما میایم کش دیفات رو bypass میکنیم و مستقیم توی دیسک مینویسم([[Cache#Fsync]])
  • یه کار دیگه هم که میکنن به صورت async از db انسپ شات میگیرن
  • و AOF: خیلی شبیه WALه و تغییرات رو مینویسه

در کل acid یه چیزیه که در [[Engine]] های دیتابیس تعریف میشه و مکانیزم های مختلفی میتونن داشته باشن

2PC and 3PC

یه تراکنش توزیع‌شده وقتی معنا پیدا می‌کنه که چند سیستم مختلف باید با هم هماهنگ یه کار رو انجام بدن، مثل کم کردن پول از حساب و رزرو موجودی در انبار. مشکل اینجاست که اگه یکی از سیستم‌ها خراب بشه یا وسط کار قطع بشه، بقیه چی‌کار کنن؟ اینجاست که پروتکل‌های commit مثل 2PC و 3PC وارد می‌شن.

در Two-Phase Commit یا همون 2PC یه Coordinator داریم که نقش مغز مرکزی رو داره. اول از همه به همه سیستم‌های شرکت‌کننده می‌گه "آماده‌ای commit کنی؟" اونا وضعیت خودشونو چک می‌کنن، منابع رو قفل می‌کنن و می‌گن آره یا نه. اگه همه گفتن آره، coordinator دستور commit می‌ده، وگرنه rollback. اینطوری اطمینان حاصل می‌کنه که یا همه موفق می‌شن یا هیچ‌کس. ولی مشکل اینجاست که اگه coordinator وسط کار بمیره، سیستم‌ها بلاتکلیف می‌مونن و ممکنه قفل‌ها آزاد نشن — یعنی کل سیستم گیر کنه.

برای حل این، Three-Phase Commit اومد. 3PC یه مرحله‌ی اضافه بین آماده شدن و commit کردن داره تا احتمال گیر کردن کمتر شه. توی فاز اول coordinator فقط می‌پرسه "می‌تونی commit کنی؟" و جواب‌ها رو جمع می‌کنه. بعد توی فاز دوم می‌گه "باشه، آماده شو ولی هنوز commit نکن." اگه همه در حالت آماده باش باشن، فاز سوم می‌گه "حالا commit کن." نکته قشنگش اینه که اگه coordinator وسط کار بمیره، سیستم‌ها می‌تونن خودشون بعد از یه مدت timeout تصمیم بگیرن commit کنن یا rollback کنن.

2PC ساده‌تره و توی خیلی از دیتابیس‌ها و سیستم‌های واقعی استفاده می‌شه، ولی ممکنه بلاک بشه. 3PC پیچیده‌تره و کمتر توی عمل دیده می‌شه، اما از نظر تئوری مقاوم‌تر در برابر crash و قطع ارتباطه. در واقع 3PC یه جور version evolved از 2PC محسوب می‌شه که سعی کرده تصمیم‌گیری رو تا جای ممکن بدون گیر کردن پیش ببره.