دیتابیس ها پشت صحنه چه سازوکاری دارند؟
دیتابیس ها پشت صحنه چه سازوکاری دارند؟
فرض کنید کاربر وسرویس هایی زیادی میخواهند هم زمان روی دیتابیس عملیات خواندن و نوشتن انجام دهند که به ان همروندی هم گفته میشود و اگر کاربران و سرویس ها بخواهند تعییرات خودشون اعمال کنن باعت بروز ناسازگاری در دیتابیس میشود حال برای جلوگیری از اتفاق باید از یک مکانیزم استفاده شود که به ان و کنترل هم روندی چند نسخه گفته میشود.
حال این روش همروندی که که به طور اختصار MVCC نام دارد به صورت کلی برای هر رکورد چند نسخه ایجاد میکند تا هر تراکنش فقط به نسخه ای دسترسی داشته باشد که اجازه دارد ببیند .ایده کلی این است که یک روشی استفاده کنیم که همروندی رو افزایش دهد.
دیتابیس های معروف چطور MVCC را پیاده سازی کرده اند؟
دیتابیس های معروف مانند postgresql و oracle و mysqlهمگی از ایده ی اصلی کنترل همروندی چندنسخه ای (MVCC) استفاده می کنند، با این تفاوت های جزئی در پیاده سازی:
- postgresql: هر تغییر در جدول، یک نسخه ی جدید از رکورد می سازد و نسخه قدیمی با علامت xmin/xmax مشخصمی شود. هر تراکنش فقط نسخه ای را می بیند که snapshot او اجازه می دهد.
- oracle: از روشی به نام undo segments استفاده میکند که نسخه ی جدید رکورد داخل جدول ساخته می شود، اما نسخه های قدیمی در undo segment ذخیره می شوند. خواننده با استفاده از undo می تواند تصویر نسخه قدیمی را بازسازی کند.
- mysql : برای هر ردیف یک rollback pointer دارد که به نسخه قبلی اشاره می کند.
مکانیزم کنترل هم روندی در postgresql چگونه پشت صحنه را مدیریت می کند؟
این مکانیزم به این صورت کار میکند که به هر تراکنش یک شماره تراکنش اختصاص میدهد مانند شماره شناسنامه که با ان xid گفته میشود و برای اینکه بتواند تشخیص دهد کدام تراکنش نسخه را ساخته است شماره تراکنش را در ستونی به اسم xmin دخیره میکند و توجه شود که این ستون ها به صورت پنهان دخیره شده اند و مکانیزم نیاز دارد بداند برای هر نسخه کدام تراکنش بر روی ان عملیات حدف یا اپدیت انجام داده است پس شماره تراکنش را در ستون xmax دخیره میکند و برای هر تراکنش نیاز است یک تصویر از دیتابیس از لحظه شروع تراکنش گرفته شود که به ان snapshotگفته میشود
مثال : دو پنجره کنار هم باز میکنیم که هرکدام برای یک تراکنش است که دو تراکنش A ,B داریم
یک جدول میسازیم
CREATE TABLE accounts (id int PRIMARY KEY, name text, balance decimal);
INSERT INTO accounts VALUES(1,10000,”ali”)
تراکنش A پنجره اول
BEGIN ISOLATION LEVEL REPEATABLE READ;
SELECT * FROM accounts WHERE id = 1;
خروجی:
1 , 10000 , ali
تراکنش B پنجره دوم
در این لحظه دیتابیس نسخه جدیدی میسازد و مقدار xmin برابر B میشود ونسخه قبلی نشان داده نمیشه و مقدارxmax برابر B میشود
BEGIN;
UPDATE accounts SET balance = 20000 WHERE id = 1;
COMMIT;
برگشت به تراکنش A
نتیجه هنوز 10000 است
چون تراکنش A قبل از تغییر شروع شده و اجازه دیدن نسخه جدید را ندارد.
SELECT * FROM accounts WHERE id = 1;
پایان تراکنش A
حال مقدار اپدیت شده 20000 دیده میشود.
COMMIT;
SELECT * FROM accounts WHERE id = 1;