پایگاه های داده و مشکلات نخ بندی

September 16th, 2008 یک نظر »

مبحث نخ بندی برنامه های سیستم عامل یا همون threadingاز جمله مسایلی هست که روی پایگاه های داده نقش بسزایی داره که هر مدیر database, طراح یا برنامه نویس وب باید به این قضیه نگاه عمیقی داشته باشه.

یکی از مشکلات بزرگ در هنگامی رخ می ده که چند مشتری در یک زمان اتصال (connection) باز با دیتابیس دارند و نحوه ی کدنویسی هم به صورتی هست که عملکرد هر کدوم بر دیگری تاثیر می ذاره. بذارید این سناریو رو بررسی کنیم که مثلا شما قضد دارید به کاربر با آی.دی 222 جایزه ی ویژه ای بدید. تا الان 221 بازدیدکننده به سایت شما سر زده و ثبت نام کرده اند. توجه کنید که در پروسه ی ثبت نام هیچ فیلد منحصر به فرد (unique field) دیگه ای جز آی.دی وجود نداره و همین آی.دی کلید اصلی جدول (primary key) هست. در این اثنا بازدید کننده ی شماره ی 222 وارد شده و شروع به وارد کردن اسم خودش می کنه. پس از این کار شما اسم رو ذخیره می کنید و کاربر رو به مرحله ی بعد پاس می دید. اسم با شماره ی 222 ذخیره می شه و تا این جای کار همه چیز درسته. در مرحله ی بعد شما چک می کنید که آیا جدول به شماره ی 222 رسیده که به بازدید کننده جایزه بدید و اون رو به فرم دریافت آدرس و شماره تلفن پاس بدید یا نه؟ برای این کار چه راهی پیشنهاد می شه؟

از اون جایی که عموما تمامی پروسه ی بالا در یک آن و یک مرحله ی اتصال انجام می شه, تنها چیزی که واقعا از کاربر در دست شماست اسم اونه و می خواید ببینید که نفر 222 ام هست یا نه؟ برای این کار راحت ترین راه حل مشاهده ی آخرین ردیف (row) وارد شده (inserted) در پایگاه داده هست. مسلما شما به راحتی قادر هستید با دستور (MAX id) و یا دستورات مشابه دریافت آخرین ردیف بر اساس نوع پایگاه داده ی خودتون, آخرین ردیف که احتمالا همون آقای 222 ام هست رو بگیرید. ولی چی می شه اگه بین دو تا خط دستورتون عمل threading اجرا بشه و برای چند لحظه این کد به حالت halt بره و آقای دیگه ای در اون سر جهان عمل ورود اسمش رو انجام بده! در این حالت سناریو به شکل زیر می شه:

A.insert(“hassan”); //id 222 automatically generates, auto_increment property

A.halt();

B.insert(“ali”); //id 223 automatically generates, auto_increment property

B.halt();

A.get_last_row(); //produces B row with id 223

B.get_last_row(); //produces B row with id 223

خب! هیچ کس که برنده نشد! ممکنه فکر کنید می تونید بگید آخرین ردیف وارد شده ای که اسمش hassan هست می تونه به ما کمک کنه! ولی توجه داشته باشید که ممکنه از شانس خوب شما, همون طور که threading ها افتاد وسط کد, اسم آقای دوم هم hassan باشه که اتفاقا اسم نادری هم نیست!

خود MySQL و حتی MSSQL برای غلبه بر این مشکل راه حل هایی با توابع داخلی خاصی ازایه داده اند که اکثرا فقط در مورد یک کاربر صدق می کنه ولی راه حل های عمومی تر ولی مشکل تری برای غلبه بر این مسئله و یا مسایل شبیه این وجود داره. از جمله:

· استفاده ازtransaction (تراکنش؟!) باعث می شه که بین دستوراتتون وقفه ی تاثیر گذار نیفته.

· استفاده از قفل/باز کردن جداول (lock/unlock)

· و یا استفاده از کدهای hash منحصر به فرد مختص هر کاربر که نیاز به ایجاد تغییراتی در جدول داره.

به هر حال در کار با دیتابیس و خصوصا در حیطه ی وب, علاوه بر توجه شدید به مسایل امنیتی و تزریقی, باید توجه بالایی هم به این گونه مسایل بشه…

مدیریت شده توسط فواد امیری, تحلیل گر, برنامه نویس و مدیر پروژه ی سیستم های مبتنی بر وب