معاملات پایگاه داده ¶

ساخت وبلاگ

Django چند روش برای کنترل نحوه مدیریت معاملات پایگاه داده به شما می دهد.

مدیریت معاملات پایگاه داده ¶

رفتار پیش فرض معامله Django ¶

رفتار پیش فرض Django این است که در حالت AutoCommit اجرا شود. هر پرس و جو بلافاصله به پایگاه داده متعهد می شود ، مگر اینکه معامله فعال باشد. برای جزئیات بیشتر به زیر مراجعه کنید.

Django از معاملات یا SavePoints به طور خودکار استفاده می کند تا یکپارچگی عملیات ORM را که به چندین نمایش داده شده نیاز دارند ، به خصوص حذف () و به روزرسانی () نمایش داده شود.

کلاس TestCase Django همچنین به دلایل عملکرد هر آزمون را در یک معامله بسته بندی می کند.

اتصال معاملات به درخواست های HTTP

یک روش مشترک برای انجام معاملات در وب ، بسته بندی هر درخواست در یک معامله است. در پیکربندی هر پایگاه داده ای که می خواهید این رفتار را فعال کنید ، Atomic_Requests را روی True تنظیم کنید.

اینگونه کار می کندقبل از فراخوانی یک تابع مشاهده ، Django معامله را شروع می کند. اگر پاسخ بدون مشکل تولید شود ، جنگو معامله را انجام می دهد. اگر این نمایش یک استثنا ایجاد کند ، Django معامله را پس می گیرد.

شما ممکن است با استفاده از SavePoints در کد مشاهده خود ، به طور معمول با مدیر متن اتمی () ، با استفاده از SavePoints را انجام دهید. با این حال ، در پایان دیدگاه ، یا هیچ یک از تغییرات انجام نمی شود.

در حالی که سادگی این مدل معامله جذاب است ، با افزایش ترافیک ، آن را ناکارآمد می کند. افتتاح معامله برای هر دیدگاه دارای سربار است. تأثیر بر عملکرد بستگی به الگوهای پرس و جو برنامه شما و چگونگی عملکرد بانک اطلاعاتی شما دارد.

معاملات هر درخواست و پاسخ های جریان

هنگامی که یک نمای یک جریان streaminghttpresponse را برمی گرداند ، خواندن محتوای پاسخ اغلب کد را برای تولید محتوا اجرا می کند. از آنجا که این نمایش قبلاً برگشته است ، چنین کدی خارج از معامله اجرا می شود.

به طور کلی ، توصیه نمی شود ضمن ایجاد پاسخ جریان ، به پایگاه داده بنویسید ، زیرا پس از شروع پاسخ ، هیچ روش معقولی برای رسیدگی به خطاها وجود ندارد.

در عمل ، این ویژگی هر عملکرد نمای را در دکوراتور اتمی () که در زیر شرح داده شده است ، بسته می کند.

توجه داشته باشید که فقط اجرای دیدگاه شما در معاملات محصور شده است. Middleware در خارج از معامله اجرا می شود ، و همچنین ارائه پاسخ های الگوی.

هنگامی که Atomic_Requests فعال می شود ، هنوز هم می توان از اجرای دیدگاه در یک معامله جلوگیری کرد.

non_atomic_requests (با استفاده از = هیچ)

این دکوراتور اثر Atomic_Requests را برای یک نمای معین نفی می کند:

از جانب django. db وارد كردن معامله @معامله.non_atomic_requests دنباله دید من(درخواست): do_stuff() @معامله.non_atomic_requests(استفاده كردن="دیگر") دنباله my_other_view(درخواست): do_stuff_on_the_other_database() 

این تنها در صورتی کار می کند که در مورد خود نمایش اعمال شود.

کنترل معاملات صریح

Django یک API واحد را برای کنترل معاملات پایگاه داده فراهم می کند.

اتمی (با استفاده از = هیچ ، SavePoint = درست ، بادوام = نادرست)

اتمی خاصیت تعیین کننده معاملات پایگاه داده است. Atomic به ما امکان می دهد تا یک بلوک از کد ایجاد کنیم که در آن اتمی در پایگاه داده تضمین شود. اگر بلوک کد با موفقیت تکمیل شود ، تغییرات به پایگاه داده متعهد می شوند. اگر یک استثنا وجود داشته باشد ، تغییرات به عقب برگردانده می شوند.

بلوک های اتمی را می توان لانه کرد. در این حالت ، هنگامی که یک بلوک داخلی با موفقیت تکمیل می شود ، اگر یک استثنا در بلوک بیرونی در یک نقطه بعدی مطرح شود ، می توان اثرات آن را به عقب برگرداند.

گاهی اوقات برای اطمینان از بلوک اتمی همیشه بیرونی ترین بلوک اتمی مفید است ، اطمینان حاصل می شود که در هنگام خروج از بلوک بدون خطا ، هرگونه تغییر پایگاه داده انجام می شود. این به دوام معروف است و با تنظیم دوام = درست می توان به دست آورد. اگر بلوک اتمی در داخل دیگری قرار بگیرد ، یک ریچر را افزایش می دهد.

اتمی هم به عنوان دکوراتور قابل استفاده است:

از جانب django. db وارد كردن معامله @معامله.مربوط به اتمی دنباله منظره(درخواست): # این کد در یک معامله اجرا می شود. do_stuff() 
از جانب django. db وارد كردن معامله دنباله منظره(درخواست): # این کد در حالت AutoCommit (پیش فرض Django) اجرا می شود. do_stuff() با معامله.مربوط به اتمی(): # این کد در یک معامله اجرا می شود. do_more_stuff() 

بسته بندی اتمی در یک آزمایش/به جز بلوک امکان رسیدگی به طبیعی خطاهای یکپارچگی را فراهم می کند:

از جانب django. db وارد كردن یکپارچه, معامله @معامله.مربوط به اتمی دنباله منظره(درخواست): ایجاد شده() تلاش كردن: با معامله.مربوط به اتمی(): تولید_براسیون() بجز یکپارچه: دستگیره() اضافه کردن() 

در این مثال ، حتی اگر GENERATE_RELATIONS () با شکستن یک محدودیت یکپارچگی باعث ایجاد خطای بانک اطلاعاتی شود ، می توانید نمایش داده ها را در add_children () اجرا کنید ، و تغییرات از creat_parent () هنوز وجود دارد و به همان معامله محدود می شود. توجه داشته باشید که هر عملیاتی که در Generate_Relations () انجام می شود () در صورت فراخوانی Handle_Exception () با خیال راحت به عقب برگردانده می شود ، بنابراین کنترل کننده استثنا در صورت لزوم می تواند در پایگاه داده نیز کار کند.

از گرفتن استثنائات در داخل اتمی خودداری کنید!

در هنگام خروج از یک بلوک اتمی ، Django به این موضوع می پردازد که آیا به طور عادی از آن خارج شده است یا به استثناء برای تعیین اینکه آیا مرتکب یا عقب نشینی می شود. اگر استثنائات را در داخل یک بلوک اتمی گرفتار کرده و از آن برخورد کنید ، ممکن است از Django این واقعیت را که مشکلی رخ داده است مخفی کنید. این می تواند منجر به رفتار غیر منتظره شود.

این بیشتر نگرانی برای DataBaseError و زیر کلاس های آن مانند EntaryError است. پس از چنین خطایی ، معامله خراب است و Django در انتهای بلوک اتمی یک بازپرداخت انجام می دهد. اگر قبل از وقوع بازپرداخت سعی در اجرای نمایش داده های پایگاه داده داشته باشید ، Django یک TransactionManagementError را جمع می کند. همچنین ممکن است با این رفتار روبرو شوید که یک کنترل کننده سیگنال مربوط به ORM یک استثنا را مطرح می کند.

روش صحیح برای گرفتن خطاهای پایگاه داده ، همانطور که در بالا نشان داده شده است ، در اطراف یک بلوک اتمی است. در صورت لزوم ، برای این منظور یک بلوک اتمی اضافی اضافه کنید. این الگوی یک مزیت دیگر دارد: صریحاً مشخص می کند که در صورت بروز یک استثنا ، کدام عملیات به عقب برگردانده می شود.

اگر استثنائاتی را که توسط نمایش داده های SQL RAW مطرح شده است ، دریافت می کنید ، رفتار Django نامشخص و وابسته به بانک اطلاعاتی است.

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

مقادیر زمینه های یک مدل هنگامی که یک بازپرداخت معامله اتفاق می افتد برگردانده نمی شوند. این می تواند به یک مدل مدل متناقض منجر شود ، مگر اینکه شما به صورت دستی مقادیر اصلی میدان را بازیابی کنید.

به عنوان مثال ، با توجه به MyModel با یک قسمت فعال ، این قطعه تضمین می کند که اگر در پایان بررسی کنید ، در صورت عدم موفقیت در True در معامله ، از مقدار صحیح استفاده می کند:

از جانب django. db وارد كردن خطای پایگاه داده, معامله تحقیر کردن = میمودل(فعال=دروغ) تحقیر کردن.فعال = درست است، واقعی تلاش كردن: با معامله.مربوط به اتمی(): تحقیر کردن.صرفه جویی() بجز خطای پایگاه داده: تحقیر کردن.فعال = دروغ if تحقیر کردن.فعال: . 

به منظور تضمین اتمی ، اتمی برخی از API ها را غیرفعال می کند. تلاش برای متعهد شدن ، عقب نشینی یا تغییر وضعیت اتمامیت اتصال پایگاه داده در یک بلوک اتمی ، یک استثنا را ایجاد می کند.

Atomic یک آرگومان با استفاده از آن را می گیرد که باید نام یک پایگاه داده باشد. اگر این استدلال ارائه نشده باشد ، Django از پایگاه داده "پیش فرض" استفاده می کند.

در زیر کاپوت ، کد مدیریت معاملات Django:

  • هنگام ورود به بیرونی ترین بلوک اتمی ، معامله را باز می کند.
  • هنگام ورود به یک بلوک اتمی داخلی ، یک نقطه ذخیره ایجاد می کند.
  • هنگام خروج از یک بلوک داخلی ، آزاد می شود یا به SavePoint باز می گردد.
  • هنگام خروج از بیرونی ترین بلوک ، معامله را مرتکب یا بازگردانید.

با تنظیم آرگومان savepoint روی False می توانید ایجاد نقاط ذخیره را برای بلوک های داخلی غیرفعال کنید. اگر یک استثنا رخ دهد، جنگو هنگام خروج از اولین بلوک والد با یک ذخیره پوینت در صورت وجود، و بیرونی ترین بلوک در غیر این صورت، بازگشت را انجام می دهد. اتمی بودن هنوز توسط معامله بیرونی تضمین شده است. این گزینه فقط در صورتی باید استفاده شود که سربار نقاط ذخیره قابل توجه باشد. این اشکال در شکستن مدیریت خطا که در بالا توضیح داده شد را دارد.

وقتی Autocommit خاموش است، می توانید از atomic استفاده کنید. این فقط از نقاط ذخیره استفاده می کند، حتی برای بیرونی ترین بلوک.

تراکنش های باز هزینه عملکردی برای سرور پایگاه داده شما دارند. برای به حداقل رساندن این سربار، تراکنش های خود را تا حد امکان کوتاه نگه دارید. اگر از atomic() در فرآیندهای طولانی مدت، خارج از چرخه درخواست/پاسخ جنگو استفاده می کنید، این امر به ویژه مهم است.

تغییر در جنگو 4. 1:

در نسخه های قدیمی تر، بررسی دوام در django. test. TestCase غیرفعال بود.

اتومات ¶

چرا جنگو از Autocommit استفاده می کند¶

در استانداردهای SQL، هر پرس و جوی SQL یک تراکنش را شروع می کند، مگر اینکه یکی از آنها قبلاً فعال باشد. پس از آن، چنین تراکنش هایی باید به صراحت انجام شود یا به عقب برگردد.

این همیشه برای توسعه دهندگان برنامه مناسب نیست. برای کاهش این مشکل، اکثر پایگاه های داده یک حالت خودکار ارائه می کنند. هنگامی که Autocommit روشن است و هیچ تراکنش فعال نیست، هر پرس و جوی SQL در تراکنش خود پیچیده می شود. به عبارت دیگر، نه تنها هر یک از این پرس و جوها یک تراکنش را شروع می کند، بلکه بسته به اینکه آیا پرس و جو موفقیت آمیز بوده است یا خیر، تراکنش به طور خودکار متعهد می شود یا بازگردانده می شود.

PEP 249، Python Database API Specification v2. 0، نیاز به خاموش شدن اولیه Autocommit دارد. جنگو این پیش فرض را لغو می کند و Autocommit را روشن می کند.

برای جلوگیری از این امر، می توانید مدیریت تراکنش را غیرفعال کنید، اما توصیه نمی شود.

غیرفعال کردن مدیریت تراکنش

با تنظیم AUTOCOMMIT روی False در پیکربندی آن، می توانید مدیریت تراکنش جنگو را برای یک پایگاه داده خاص غیرفعال کنید. اگر این کار را انجام دهید، جنگو کامیت خودکار را فعال نمی کند و هیچ تعهدی را انجام نمی دهد. رفتار منظم کتابخانه پایگاه داده زیربنایی را دریافت خواهید کرد.

این امر مستلزم آن است که هر تراکنش را به صراحت انجام دهید، حتی آنهایی که توسط جنگو یا کتابخانه های شخص ثالث آغاز شده اند. بنابراین، این به بهترین وجه در شرایطی استفاده می شود که می خواهید میان افزار کنترل کننده تراکنش خود را اجرا کنید یا کاری واقعاً عجیب انجام دهید.

انجام اقدامات پس از انجام تعهد¶

بعضی اوقات شما نیاز به انجام یک عمل مربوط به معامله پایگاه داده فعلی دارید ، اما فقط در صورت موفقیت معامله انجام می شود. مثالها ممکن است شامل یک کار پس زمینه ، اعلان ایمیل یا عدم اعتبار حافظه پنهان باشد.

on_commit () به شما امکان می دهد تماس های تماس تلفنی را که پس از انجام معامله باز با موفقیت انجام می شود ، ثبت کنید:

on_commit (عملکرد ، با استفاده از = هیچ ، قوی = نادرست)

یک تابع یا هر تماس گیرنده را به on_commit () منتقل کنید:

از جانب django. db وارد كردن معامله دنباله send_welcome_email(): . معامله.on_commit(send_welcome_email) 

تماس های برگشتی به هیچ استدلال منتقل نمی شود ، اما می توانید آنها را با functools. partial () وصل کنید.

از جانب کله پاچه وارد كردن جزئي برای کاربر in کاربران: معامله.on_commit(جزئي(send_invite_email, کاربر=کاربر)) 

پس از انجام معاملات باز با موفقیت ، تماس تلفنی فراخوانی می شود. اگر معامله به جای آن به عقب برگردد (به طور معمول هنگامی که یک استثناء نامشخص در یک بلوک اتمی () مطرح شود) ، پاسخ به تماس دور می شود و هرگز فراخوانی نمی شود.

اگر در حالی که یک معامله باز وجود ندارد ، با on_commit () تماس بگیرید ، پاسخ به تماس بلافاصله اجرا می شود.

ثبت نام های تماس تلفنی که می توانند شکست بخورند ، گاهی مفید است. عبور قوی = درست اجازه می دهد تا تماس های بعدی حتی اگر مورد فعلی استثنائی را انجام دهد ، اجرا شود. تمام خطاهای ناشی از کلاس استثناء پایتون گرفتار شده و به logger django. db. backends. base وارد شده اند.

می توانید از TestCase. CaptureOnCommitCallbacks () برای آزمایش تماس های تماس گرفته شده در on_commit () استفاده کنید.

تغییر در Django 4. 2:

استدلال قوی اضافه شد.

SavePoints¶

SavePoints (به عنوان مثال بلوک های اتمی تو در تو) به درستی اداره می شوند. یعنی پس از انجام معامله بیرونی ، یک تماس تلفنی on_commit () ثبت شده پس از SavePoint (در یک بلوک اتمی تومیک ()) نامیده می شود ، اما در صورت عدم بازگشت به آن SavePoint یا هرگونه SavePoint قبلی در طول معامله رخ داده است:

با معامله.مربوط به اتمی(): # اتمی بیرونی ، یک معامله جدید را شروع کنید معامله.on_commit(فحش) با معامله.مربوط به اتمی(): # بلوک اتمی داخلی ، یک SavePoint ایجاد کنید معامله.on_commit(بار) # foo () و سپس نوار () هنگام ترک بیرونی ترین بلوک فراخوانده می شود 

از طرف دیگر ، هنگامی که یک SavePoint به عقب برگردانده می شود (به دلیل استثناء مطرح شده) ، تماس داخلی نامیده نمی شود:

با معامله.مربوط به اتمی(): # اتمی بیرونی ، یک معامله جدید را شروع کنید معامله.on_commit(فحش) تلاش كردن: با معامله.مربوط به اتمی(): # بلوک اتمی داخلی ، یک SavePoint ایجاد کنید معامله.on_commit(بار) بالا بردن برخی() # بالا بردن یک استثنا - سقط جنین SavePoint بجز برخی: عبور # foo () نامیده می شود ، اما نوار () نیست 

ترتیب اعدام ¶

توابع تعهد برای یک معامله معین به ترتیب ثبت شده اجرا می شوند.

رسیدگی به استثنا

اگر یک تابع محدودیت ثبت شده با Strong = False در یک معامله معین ، یک استثناء غیرقانونی را ایجاد کند ، عملکردهای بعدی ثبت شده در همان معامله اجرا نمی شود. این همان رفتار است که اگر شما توابع را به طور متوالی خود بدون on_commit () اجرا کرده اید.

تغییر در Django 4. 2:

استدلال قوی اضافه شد.

زمان اعدام

تماس های برگشت شما پس از یک تعهد موفق اجرا می شود ، بنابراین عدم موفقیت در پاسخ به تماس باعث بازگشت معامله نمی شود. آنها به دلیل موفقیت معامله به صورت مشروط اجرا می شوند ، اما بخشی از معامله نیستند. برای موارد استفاده در نظر گرفته شده (اعلان های پستی ، کارهای پس زمینه و غیره) ، این باید خوب باشد. اگر اینگونه نباشد (اگر عمل پیگیری شما آنقدر مهم است که شکست آن باید به معنای عدم موفقیت معامله باشد) ، پس نمی خواهید از قلاب on_commit () استفاده کنید. درعوض ، ممکن است شما بخواهید تعهد دو فاز مانند پشتیبانی از پروتکل دو فاز Psycopg و پسوندهای متعهد دو فاز اختیاری در مشخصات Python DB-API داشته باشید.

تماس تلفنی تا زمانی که AutomMit در اتصال به دنبال تعهد ترمیم نشود ، اجرا نمی شود (در غیر این صورت هر پرس و جو انجام شده در پاسخ به تماس ، یک معامله ضمنی را باز می کند و مانع از بازگشت اتصال به حالت AutomMomit می شود).

هنگامی که در حالت AutoCommit و خارج از یک بلوک اتمی () قرار دارد ، عملکرد بلافاصله اجرا می شود ، نه در تعهد.

توابع مربوط به تجارت فقط با حالت AutomMit و API معامله اتمی (یا Atomic_Requests) کار می کنند. تماس با on_commit () در هنگام غیرفعال بودن اتمیت و شما در یک بلوک اتمی به خطایی منجر می شوید.

در تست ها استفاده کنید

کلاس TestCase Django هر آزمون را در یک معامله بسته بندی می کند و پس از هر آزمون ، آن معامله را به عقب می اندازد ، تا بتواند انزوای آزمون را ارائه دهد. این بدان معناست که هیچ معامله ای در واقع انجام نشده است ، بنابراین تماس های برگشت () شما هرگز اجرا نمی شود.

شما می توانید با استفاده از TestCase. CaptureOnCommitCallbacks () بر این محدودیت غلبه کنید. این تماس های برگشتی on_commit () شما را در یک لیست ضبط می کند و به شما امکان می دهد تا در مورد آنها ادعا کنید یا با تماس با آنها معامله را تقلید کنید.

راه دیگر برای غلبه بر محدودیت استفاده از TransactionTestcase به جای TestCase است. این بدان معنی است که معاملات شما انجام شده است و تماس های برگشتی اجرا می شود. با این حال TransactionTestcase پایگاه داده را بین تست ها می اندازد ، که به طور قابل توجهی کندتر از جداسازی TestCase است.

چرا قلاب برگشت؟

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

به عنوان مثال ، اگر اتصال پایگاه داده شما کاهش یافته باشد زیرا روند شما بدون فرصتی برای خاموش کردن با لطف کشته شد ، قلاب برگشت شما هرگز اجرا نمی شود.

اما یک راه حل وجود دارد: به جای انجام کاری در طول بلوک اتمی (معامله) و سپس خنثی کردن آن در صورت عدم موفقیت معامله ، از on_commit () استفاده کنید تا این کار را در وهله اول به تأخیر بیندازد تا پس از موفقیت معامله. خنثی کردن کاری که هرگز در وهله اول انجام نداده اید بسیار ساده تر است!

APIS سطح پایین

همیشه در صورت امکان اتمی () را ترجیح دهید. این خصوصیات خاص هر پایگاه داده را به خود اختصاص داده و از عملیات نامعتبر جلوگیری می کند.

API های سطح پایین فقط در صورت اجرای مدیریت معامله خود مفید هستند.

اتومات ¶

Django یک API را در ماژول django. db. transaction برای مدیریت وضعیت اتمامیت هر اتصال بانک اطلاعاتی فراهم می کند.

get_autocommit (با استفاده از = هیچ) ¶ set_autocommit (autommitmit ، با استفاده از = هیچ)

این توابع یک آرگومان استفاده می کنند که باید نام یک پایگاه داده باشد. در صورت عدم ارائه ، Django از پایگاه داده "پیش فرض" استفاده می کند.

AutoCommit در ابتدا روشن است. اگر آن را خاموش کنید ، وظیفه شماست که آن را بازیابی کنید.

پس از خاموش کردن AutoCommit ، رفتار پیش فرض آداپتور پایگاه داده خود را دریافت می کنید ، و Django به شما کمک نمی کند. اگرچه این رفتار در PEP 249 مشخص شده است ، اما اجرای آداپتورها همیشه با یکدیگر سازگار نیستند. مستندات آداپتور مورد نظر خود را با دقت مرور کنید.

شما باید اطمینان حاصل کنید که هیچ معامله ای معمولاً با صدور تعهد () یا برگشت () () قبل از بازگشت خودکار خودکار فعال نیست.

Django در هنگام فعال بودن یک بلوک اتمی () از خاموش کردن اتمیت خودداری می کند ، زیرا این امر اتمی را می شکند.

معاملات

معامله یک مجموعه اتمی از پرس و جوهای پایگاه داده است. حتی اگر برنامه شما خراب شود ، بانک اطلاعاتی تضمین می کند که یا همه تغییرات اعمال می شود ، یا هیچ یک از آنها.

Django برای شروع معامله API ارائه نمی دهد. راه مورد انتظار برای شروع معامله ، غیرفعال کردن AutoCommit با SET_AUTOCMOMMIT () است.

پس از معامله ، می توانید تغییراتی را که انجام داده اید تا این مرحله با تعهد () اعمال کنید ، یا آنها را با بازگشت () لغو کنید. این توابع در django. db. transaction تعریف شده اند.

متعهد (با استفاده از = هیچ) ¶ برگشت (با استفاده از = هیچ)

این توابع یک آرگومان استفاده می کنند که باید نام یک پایگاه داده باشد. در صورت عدم ارائه ، Django از پایگاه داده "پیش فرض" استفاده می کند.

در هنگام فعال بودن یک بلوک اتمی () ، جنگو از تعهد یا بازگشت به عقب امتناع می ورزد ، زیرا این امر باعث ایجاد اتمی می شود.

SavePoints¶

SavePoint یک نشانگر در معامله ای است که به شما امکان می دهد بخشی از یک معامله را به جای معامله کامل بازگردانید. SavePoints با پشتیبان های SQLite ، PostgreSQL ، Oracle و MySQL (هنگام استفاده از موتور ذخیره سازی IoDB) در دسترس است. سایر باکتری ها عملکردهای SavePoint را ارائه می دهند ، اما آنها عملیات خالی هستند - آنها واقعاً کاری انجام نمی دهند.

اگر از AutomMit ، رفتار پیش فرض Django استفاده می کنید ، SavePoints مخصوصاً مفید نیستند. با این حال ، پس از باز کردن معامله با Atomic () ، شما یک سری از عملیات پایگاه داده را در انتظار یک تعهد یا بازپرداخت ایجاد می کنید. اگر یک بازپرداخت صادر کنید ، کل معامله به عقب برگردانده می شود. SavePoints امکان انجام یک برگشتی ریز دانه را فراهم می کند ، به جای بازگشت کامل که توسط Transaction. Rollback () انجام می شود.

هنگامی که دکوراتور اتمی () توخالی می شود ، یک نقطه ذخیره ایجاد می کند تا امکان تعهد یا بازگشت جزئی را فراهم کند. شما به شدت به استفاده از اتمی () به جای توابع شرح داده شده در زیر تشویق می شوید ، اما آنها هنوز هم بخشی از API عمومی هستند ، و هیچ برنامه ای برای کاهش آنها وجود ندارد.

هر یک از این توابع یک آرگومان استفاده می کنند که باید نام پایگاه داده ای باشد که برای آن رفتار اعمال می شود. در صورت عدم استفاده از آرگومان ، از پایگاه داده "پیش فرض" استفاده می شود.

SavePoints توسط سه عملکرد در django. db. transaction کنترل می شود:

SavePoint (با استفاده از = هیچ)

SavePoint جدید ایجاد می کند. این یک نکته در معامله است که شناخته شده است که در حالت "خوب" قرار دارد. شناسه SavePoint (SID) را برمی گرداند.

savePoint_commit (sid ، با استفاده از = هیچ)

SavePoint SID را منتشر می کند. تغییرات انجام شده از زمان ایجاد SavePoint بخشی از معامله شد.

savePoint_rollback (sid ، با استفاده از = هیچ)

معامله را به عقب برگردانید تا SavePoint SID.

این توابع در صورت پشتیبانی از SavePoints یا اینکه پایگاه داده در حالت AutomMit است ، کاری انجام نمی دهند.

علاوه بر این ، یک عملکرد ابزار وجود دارد:

Clean_SavePoints (با استفاده از = هیچ)

پیشخوان مورد استفاده برای تولید شناسه های منحصر به فرد SavePoint را تنظیم می کند.

مثال زیر استفاده از SavePoints را نشان می دهد:

از جانب django. db وارد كردن معامله # معامله را باز کنید @معامله.مربوط به اتمی دنباله منظره(درخواست): a.صرفه جویی() # معامله اکنون شامل A. Save () سید = معامله.نقطه() b.صرفه جویی() # معامله اکنون شامل A. Save () و B. Save () است if Want_TO_KEEP_B: معامله.savePoint_commit(سید) # معامله باز هنوز شامل A. Save () و B. Save () است دیگر: معامله.savePoint_rollback(سید) # معامله باز اکنون فقط شامل a. save () 

SavePoints ممکن است برای بازیابی از خطای بانک اطلاعاتی با انجام یک بازگشت جزئی جزئی استفاده شود. اگر این کار را در داخل یک بلوک اتمی () انجام می دهید ، کل بلوک هنوز به عقب برگردانده می شود ، زیرا نمی داند شما وضعیت را در سطح پایین تر اداره کرده اید! برای جلوگیری از این امر ، می توانید رفتار برگشت با عملکردهای زیر را کنترل کنید.

get_rollback (با استفاده از = هیچ) ¶ set_rollback (بازگشت ، با استفاده از = هیچ)

هنگام خروج از بلوک اتمی درونی ، پرچم بازپرداخت را به صورت واقعی بازپرداخت می کند. این ممکن است برای ایجاد برگشت به عقب بدون ایجاد یک استثنا مفید باشد.

تنظیم آن در False از چنین بازگشت مجدد جلوگیری می کند. قبل از انجام این کار ، اطمینان حاصل کنید که معامله را به یک نقطه ذخیره خوب شناخته شده در بلوک اتمی فعلی برگردانید! در غیر این صورت ممکن است اتمی و فساد داده را بشکنید.

یادداشت های خاص بانک اطلاعاتی

SavePoints در SQLite¶

در حالی که SQLite از SavePoints پشتیبانی می کند ، نقص در طراحی ماژول SQLite3 باعث می شود آنها به سختی قابل استفاده باشند.

هنگامی که AutoCommit فعال شد ، SavePoints معنی ندارد. هنگامی که غیرفعال است ، SQLite3 قبل از اظهارات SavePoint به طور ضمنی مرتکب می شود.(در واقع ، قبل از هر جمله ای غیر از انتخاب ، درج ، به روزرسانی ، حذف و جایگزینی تعهد می کند.) این اشکال دو پیامدهای دارد:

  • API های سطح پایین برای SavePoints فقط در یک معامله یعنی داخل یک بلوک اتمی () قابل استفاده هستند.
  • استفاده از اتمی () هنگام خاموش شدن اتمی غیرممکن است.

معاملات در mysql¶

اگر از MySQL استفاده می کنید ، جداول شما ممکن است از معاملات پشتیبانی کند یا نباشد. این بستگی به نسخه MySQL شما و انواع جدول شما استفاده می کند.(با "انواع جدول" ، منظور ما چیزی مانند "IoDB" یا "MyIsam" است.) خصوصیات معاملات MySQL خارج از محدوده این مقاله است ، اما سایت MySQL اطلاعاتی در مورد معاملات MySQL دارد.

اگر تنظیمات MySQL شما از معاملات پشتیبانی نمی کند ، Django همیشه در حالت AutomMitt عمل می کند: بیانیه ها به محض فراخوانی آنها اجرا و متعهد می شوند. اگر تنظیمات MySQL شما از معاملات پشتیبانی می کند ، Django مطابق با این سند معاملات را انجام می دهد.

رسیدگی به استثنائات در معاملات postgreSQL

این بخش فقط در صورت اجرای مدیریت معاملات شخصی خود مرتبط است. این مشکل نمی تواند در حالت پیش فرض Django رخ دهد و اتمی () آن را به طور خودکار انجام می دهد.

در داخل یک معامله ، هنگامی که تماس با یک مکان نما PostgresQL یک استثناء (به طور معمول یکپارچه سازی) ایجاد می کند ، تمام SQL بعدی در همان معامله با خطا شکست می خورند "معامله فعلی سقط شده است ، سؤالات نادیده گرفته شده تا پایان بلوک معامله". در حالی که استفاده اصلی از Save () بعید است که یک استثناء در PostgreSQL ایجاد کند ، الگوهای استفاده پیشرفته تری وجود دارد که ممکن است مانند صرفه جویی در اشیاء با زمینه های منحصر به فرد ، صرفه جویی در استفاده از پرچم Force_Insert/Force_Update یا فراخوانی SQL سفارشی.

روش های مختلفی برای بازیابی از این نوع خطا وجود دارد.

بازپرداخت معاملات

گزینه اول این است که کل معامله را پس بگیرید. مثلا:

a.صرفه جویی() # موفق می شود ، اما ممکن است با بازپرداخت معامله خنثی شود تلاش كردن: b.صرفه جویی() # می تواند استثنا را پرتاب کند بجز یکپارچه: معامله.بازپرداخت() c.صرفه جویی() # موفق می شود ، اما a. save () ممکن است خنثی شده باشد 

تماس با معامله. rollback () کل معامله را به عقب می اندازد. هرگونه عملیات بدون استفاده از پایگاه داده از بین می رود. در این مثال ، تغییرات ایجاد شده توسط A. Save () از بین می رود ، حتی اگر این عمل هیچ خطایی ایجاد نکند.

SavePoint Rollback¶

برای کنترل میزان بازگشت مجدد می توانید از SavePoints استفاده کنید. قبل از انجام عملیات پایگاه داده ای که می تواند شکست بخورد ، می توانید SavePoint را تنظیم یا به روز کنید. به این ترتیب ، اگر این عملیات از بین برود ، می توانید به جای کل معامله ، عملیات متخلف را به عقب برگردانید. مثلا:

a.صرفه جویی() # موفق می شود ، و هرگز توسط SavePoint Rollback خنثی نمی شود سید = معامله.نقطه() تلاش كردن: b.صرفه جویی() # می تواند استثنا را پرتاب کند معامله.savePoint_commit(سید) بجز یکپارچه: معامله.savePoint_rollback(سید) c.صرفه جویی() # موفق می شود ، و a. save () هرگز خنثی نمی شود 

در این مثال ، A. Save () در موردی که B. Save () یک استثنا را ایجاد نمی کند ، خنثی نمی شود.

پرسش و پاسخ بورس...
ما را در سایت پرسش و پاسخ بورس دنبال می کنید

برچسب : نویسنده : ماندانا اصلانی بازدید : <-PostHit-> تاريخ : جمعه 20 مرداد 1402 ساعت: 1:27