درک قفل خوش بینانه و بدبینانه در Ruby on Rails

هنگامی که چندین نفر به طور همزمان یک پایگاه داده را لمس می کنند، زمانی که بیش از یک کاربر سعی می کنند یک رکورد را به روز کنند، تداخل نرم افزاری ممکن است رخ دهد. بهترین راه برای جلوگیری از مشکلات از این نظر، قفل کردن رکوردی است که اولین کاربر باید تغییر دهد. این گونه درگیری ها در Ruby on Rails با استفاده از دو راهبرد قفل کردن بررسی می شوند: قفل خوش بینانه و قفل بدبینانه. این مقاله درباره این استراتژیها، تفاوتهای آنها و نحوه پیادهسازی آنها در Ruby on Rails بحث میکند.
قفل خوش بینانه
قفل خوش بینانه فرض می کند که درگیری ها نادر هستند. این به چندین کاربر اجازه میدهد تا یک رکورد را بدون محدودیت بخوانند، اما با تأیید نسخه رکورد قبل از ذخیره، مطمئن میشود که بهروزرسانیها ایمن هستند.
چگونه کار می کند
- الف
version
ستون به جدول اضافه می شود. - هر بار که یک رکورد به روز می شود،
version
افزایش می یابد. - وقتی کاربر سعی می کند تغییرات را ذخیره کند، Rails بررسی می کند که آیا
version
در پایگاه داده مطابقت داردversion
در شی کاربر - اگر نسخه ها مطابقت نداشته باشند، Rails یک خطا ایجاد می کند (به عنوان مثال،
ActiveRecord::StaleObjectError
، نشان می دهد که رکورد توسط شخص دیگری به روز شده است.
مثال در ریل
# Migration to add version column
class AddLockVersionToUsers < ActiveRecord::Migration[7.0]
def change
add_column :users, :lock_version, :integer, default: 0, null: false
end
end
راه اندازی مدل
class User < ApplicationRecord
end
استفاده در کد
user1 = User.find(1)
user2 = User.find(1)
user1.update(name: "Alice")
user2.update(name: "Bob") # Raises ActiveRecord::StaleObjectError
قفل بدبینانه
قفل بدبینانه با قفل کردن یک رکورد برای یک کاربر در طول یک عملیات از درگیری جلوگیری می کند. سایر کاربران نمی توانند رکورد را تغییر دهند یا حتی آن را بخوانند (بسته به نوع قفل) تا زمانی که قفل آزاد نشود.
چگونه کار می کند
- یک قفل در سطح پایگاه داده زمانی اعمال می شود که به یک رکورد دسترسی پیدا می شود.
- سایر تراکنش ها باید منتظر بمانند تا قفل آزاد شود.
- این از درگیری جلوگیری می کند، اما اگر قفل ها برای مدت طولانی نگه داشته شوند، می تواند منجر به مشکلات عملکرد شود.
مثال در ریل
# Usage with find and lock
user = User.lock.find(1) # Applies a "FOR UPDATE" lock in SQL
user.update(name: "Charlie") # Other transactions must wait
استفاده در یک معامله
User.transaction do
user = User.lock.find(1)
user.update(name: "Dana")
end
تفاوت بین قفل خوش بینانه و بدبینانه
ویژگی | قفل خوش بینانه | قفل بدبینانه |
---|---|---|
فرض | درگیری ها نادر است. | درگیری ها محتمل است. |
پیاده سازی | استفاده می کند a version ستون برای تشخیص تضادها |
از قفل های پایگاه داده برای جلوگیری از درگیری استفاده می کند. |
عملکرد | بدون انتظار برای قفل، بهتر است برای برنامه های با خواندن بالا. | در صورت استفاده بیش از حد می تواند باعث تاخیر و بن بست شود. |
حل تعارض | هنگامی که یک تضاد شناسایی می شود، یک خطا ایجاد می کند. | با قفل کردن رکورد از درگیری جلوگیری می کند. |
استفاده از مورد | بهترین برای برنامه هایی با خواندن مکرر و به روز رسانی نادر. | بهترین برای عملیات حیاتی که نیاز به کنترل دقیق دارند. |
انتخاب استراتژی مناسب
از قفل خوش بینانه استفاده کنید وقتی:
- این برنامه دارای نسبت خواندن به نوشتن بالایی است.
- درگیری ها نادر هستند اما باید شناسایی شوند.
- کاربران باید تضادها را به صورت دستی حل کنند.
از قفل بدبینانه استفاده کنید وقتی:
- تعارضات رایج یا بحرانی هستند.
- یکپارچگی داده ها مهمتر از عملکرد است.
- معاملات کوتاه و به خوبی مدیریت می شوند.
خلاصه
قفل خوش بینانه ساده و سبک وزن است، در حالی که قفل بدبینانه کنترل دقیقی را به قیمت مشکلات احتمالی عملکرد ارائه می دهد. اینکه کدام یک استفاده شود به نیازهای خاص یک برنامه و الگوی استفاده بستگی دارد.