خواندن داده ها در پايگاه داده به صورت سازگار و با قفل گذاري

images

خواندن سازگار بدون قفل گذاري يك خواندن سازگار بدين معني است كه اینودی‌بي از چند نسخه اي براي تهيه يك تصوير از پايگاه داده موقع اجراي پرس و جو استفاده مي كند و آن پرس و جو فقط تغييرات اعمال شده توسط تراكنش هاي اجرا شده قبل از آن نقطه از زمان را مي بيند و تغييرات اعمال شده توسط تراكنش هاي بعدي و يا آنهايي كه اعمال نشده اند را نمي تواند مشاهده كند. اما استثناي اين قانون اين است كه پرسجو تغييرات قبلي اعمال شده در همان تراكنش را مشاهده مي كند. اين استثنا باعث بوجود آمدن اين اختلاف مي شود كه ممكن است هنگامي كه يك تراكنش تعدادي از سطر ها را بروز رساني ميكند دستور Select علاوه بر تغييرات جديد اعمال شده نسخه هاي قديمي سطر ها را نيز ببيند و اگر نشست هاي ديگر نيز به طور پيوسته جدول را بروز رساني كنند ممكن است تراكنش نسخه اي از جدول را كه اكنون در پايگاه داده وجود ندارد را مشاهده كند. اگر سطح ايزوله سازي برابر با مقدار پيشفرض REPEATEABLE_READ باشد تمام خواندن هاي سازگار در يك تراكنش از يك تصوير ايجاد شده در اولين خواندن استفاده مي كنند و مي توانيد با اعمال تراكنش جاري و ايجاد يك پرس و جوي جديد تصاوير جديدتري ايجاد نماييد. با استفاده از سطح READ_COMMITED هر يك از خواندن هاي سازگار از تصوير جديد ايجاد شده براي خود استفاده مي كنند. خواندن سازگار بطور پيشفرض در اینودی‌بي براي پردازش SELECT در سطوح READ_COMMITED و REPEATED_READ استفاده مي شود. يك خواندن سازگار هيچ قفلي را روي جدول هاي مورد دسترسي خود ايجاد نمي كند و به همين دليل ساير نشست ها مجاز به تغيير آن جدول در هنگامي كه خواندن انجام مي شود هستند. فرض كنيد شما از حالت پيشفرض استفاده مي كنيد. در اين صورت با اجراي يك خواندن سازگار كه همان دستور SELECT معمولي هست يك نقطه زماني به تراكنش شما اعطا مي شود كه در آن نقطه پرس و جو پايگاه داده را مشاهده ميكند. اگر يك تراكنش ديگر بعد از آن نقطه زماني يك سطر جدول را حذف كند و تغييرات را اعمال كند شما آن سطر را نخواهيد ديد به همين طريق با دستور هاي بروزرساني و درج برخورد مي شود. تصوير وضعيت پايگاه داده براي دستور SELECT در تراكنش اعمال مي شود و نه الزاما براي دستور هاي DML. اگر شما سطر هايي را تغيير دهيد يا درج نماييد و آن تراكنش را اعمال كنيد يك دستور خواندن يا بروزرساني كه توسط يك تراكنش همزمان از نوع REPEATEABLE_READ صادر شده باشد سطر هاي جديد اعمال شده را تحت تاثير قرار مي دهد حتي اگر پرس و جو نتواند آنها را ببيند. اگر يك تراكنش سطر هاي اعمال شده توسط يك تراكنش ديگر را بروزرساني يا حذف كند آن تغييرات براي تراكنش جاري مشاهده پذير خواهند بود. به عنوان مثال ممكن است با يك موقعيت مانند آنچه در پايين اشاره شده مواجه شويد: SELECT COUNT(c1) FROM t1 WHERE c1 = ‘xyz'; — Returns 0: no rows match. DELETE FROM t1 WHERE c1 = ‘xyz'; — Deletes several rows recently committed by other transaction. SELECT COUNT(c2) FROM t1 WHERE c2 = ‘abc'; — Returns 0: no rows match. UPDATE t1 SET c2 = ‘cba’ WHERE c2 = ‘abc'; — Affects 10 rows: another txn just committed 10 rows with ‘abc’ values. SELECT COUNT(c2) FROM t1 WHERE c2 = ‘cba'; — Returns 10: this txn can now see the rows it just updated. شما مي توانيد نقطه زماني را با اعمال كردن تراكنش جاري و اجراي يك دستور مجدد مانند SELECT يا START_TRANSACTION_WITH_CONSISTENT_SNAPSHOT جلو ببريد. به اين عمل كنترل سازگاري چند نسخه اي مي گويند. در مثال زير نشست A سطر هاي درج شده توسط B را فقط در صورتي كه B آنها را اعمال كند و A نيز به همين صورت اعمال شود تا نقطه زماني آن جلو تر از زمان اعمالB برود ، مشاهده خواهد كرد. Session A Session B SET autocommit=0; SET autocommit=0; time | SELECT * FROM t; | empty set | INSERT INTO t VALUES (1, 2); | v SELECT * FROM t; empty set COMMIT; SELECT * FROM t; empty set COMMIT; SELECT * FROM t; ——————— | ۱ | ۲ | ——————— ۱ row in set اگر مي خواهيد جديد ترين تصوير پايگاه داده را ببينيد بايد يا از سطح READ_COMMITED و يا خواندن هاي با قفل گذاري استفاده كنيد. SELECT * FROM t LOCK IN SHARE MODE; با استفاده از سطح READ_COMMITED هر تراكنش با ايجاد يك تصوير جديد از پايگاه داده براي خود از آن براي خواندن استفاده مي كند. اما با ساتفاده از LOCK IN SHARE MODE يك قفل گذاري اتفاق مي افتد و دستور SELECT تا زماني كه تراكنش داراي جديد ترين تصوير به اتمام برسد مسدود مي شود. خواندن هاي سازگار روي برخي از دستورات DDL كار نمي كنند: • خواندن هاي سازگار روي DROP TABLE كار نميكنند چون كه ماي اسكيوال نمي تواند با جدول هاي Drop شده كار كند و اینودی‌بي آن جدول ها را پاك مي كند. • خواندن هاي سازگار روي ALTER TABLE كار نمي كند به اين دليل كه اين دستور يك كپي موقت از جدول تهيه مي كند و بعد از آن جدول اصلي را حذف ميكند. هنگامي كه يك دستور خواندن سازگار در يك تراكنش صادر شود سطر ها و جدول ها قابل مشاهده نيستند زيرا هنگامي كه تصوير تراكنش گرفته شده است وجود نداشته اند. در اين مورد يك خطا به صورت ER_TABLE_DEF_CHANGED برميگرداند. انواع خواندن براي دستور هاي SELECT متفاوت هست مانند INSERT INTO … SELECT ، UPDATE … SELECT ، و CREATE TABLE … SELECT كه در آنها FOR UPDATE يا LOCK IN SHARE MODE مشخص نشده است: • به صورت پيشفرض اینودی‌بي از قفل هاي قوي تر استفاده ميكند و SELECT نيز به صورت READ COMMITED استفاده مي شود. • براي استفاده از يك خواندن سازگار در اين شرايط بايد گزينه ي INNODB_LOCKS_UNSAFE_FOR_BINLOC را فعال نماييد و سطح ايزوله سازي را به يكي از حالت هاي READ UNCOMMITED ، READ COMMITED يا REPEATED READ تغيير دهيد و در اين صورت هيچ قفلي روي سطر هاي درحال خوانده شدن قرار نمي گيريد. خواندن با قفل گذاري اگر شما در يك ترامنش علاوه بر پرس و جوي داده ها اقدام به درج يا بروزرساني داده ها نماييد استفاده از دستور معمولي SELECT حفاظت كافي را ايجاد نمي كند و ساير تراكنش ها مي توانند سطر هايي را كه جستجو كرده ايد را بروزرساني يا حذف كنند . اینودی‌بي از دو نوع خواندن با قفل گذاري پشتيباني ميكند كه محافظت بيشتري را ارائه ميكنند: • دستور SELECT …. LOCK IN SHARE MODE يك قفل از نوع اشتراكي روي سطر ها هنگام خواندن ايجاد مي كند در اين صورت ساير تراكنش ها مي توانند آن سطر ها را بخوانند ولي نمي توانند تغييراتي را روي آن اعمال كنند تا زماني كه تراكنش شما به پايان برسد. همچنين در اين حالت اگر سطر هايي كه مي خواهيد بخوانيد توسط تراكنش ديگري تغيير كرده باشند تراكنش شما منتظر مي ماند تا آن تغييرات اعمال شوند و سپس از آخرين مقادير براي خواندن استفاده خواهد كرد. • براي ركورد هاي شاخص ،دستور SELECT …. FOR UPDATE سطر ها و تمامي شاخص هاي وابسطه را مانند هنگام بروزرساني قفل گذاري ميكند در اين صورت ساير تراكنش ها نمي توانند آن سطر ها را بروزرساني نموده يا دستور SELECT .. LOCK IN SHARE MODE را روي آن اجرا كنند. خواندن هاي سازگار تمامي قفل هاي موجود روي سطر ها را ناديده ميگيرند. اين نوع دستورات هنگام برخورد با داده هاي دختي يا گرافي در يك جدول يا به صورت جدا در چندين جدول مفيد خواهند بود. در اين صورت شما رائس هاي گراف يا برگ هاي درخت را پيمايش نموده و حق داريد به عقب برگشته و هر يك از اين اشاره گرها را تغيير دهيد. تمام قفل هاي تنظيم شده توسط LOCK IN SHARE MODE و FOR UPDATE زماني كه تراكنش ها اعمال شوند يا به عقب بازگردند آزاد خواهند شد. نكته : قفل كردن سطر ها براي بروزرساني با استفاده از SELECT FOR UPDATE زماني كه AUTOCOMMIT غير فعال باشد كار ميكنند و در صورتي كه AUTOCOMMIT فعال باشد سطر هاي مشخص شده قفل نخواهند شد.

درباره نویسنده

نوشته های مرتبط

نظری بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *