paint-brush
Python - Django: Siz hech qachon bu narsalarni tranzaktsiyalarga qo'ymasligingiz keraktomonidan@mta
Yangi tarix

Python - Django: Siz hech qachon bu narsalarni tranzaktsiyalarga qo'ymasligingiz kerak

tomonidan Michael T. Andemeskel17m2025/03/04
Read on Terminal Reader

Juda uzoq; O'qish

Tranzaksiyalar Django ilovalarida markaziy oʻrin tutadi, lekin agar siz tranzaksiyalarga notoʻgʻri kod kiritsangiz, uzilishga olib kelishi mumkin!
featured image - Python - Django: Siz hech qachon bu narsalarni tranzaktsiyalarga qo'ymasligingiz kerak
Michael T. Andemeskel HackerNoon profile picture


Tarkib

  • 1-qism Xulosa - Django operatsiyalariga chuqur kirib boring
  • TLDR, xulosa
  • Tranzaksiyalar bizning ilovalarimizga qanday zarar etkazishi mumkin?
  • In
  • Xavfli
  • Chiqib ketdi
  • Keyingi - PSQL buyruqlari bir-birini qanday bloklaydi
  • Manbalar

1-qism Xulosa - Django operatsiyalariga chuqur sho'ng'ish

Oldingi postda biz transaction.atomic bilan bezatilgan funksiya chaqirilganda nima sodir bo'lishini va with transaction.atomic() nima sodir bo'lishini bilib oldik. Qisqa bayoni; yakunida:


  1. JBga ulanish yaratiladi yoki olinadi.
  2. Tranzaksiya yaratiladi, masalan, BEGIN; ma'lumotlar bazasiga yuboriladi (agar JB PSQL yoki boshqa SQL varianti bo'lsa).
  3. Bundan buyon funktsiya mavjud bo'lgunga qadar yoki with iborasi tugaguniga qadar - xato yoki muvaffaqiyatli - biz tranzaktsiyada bo'lamiz va JB bizni kutadi.
  4. Bu shuni anglatadiki, (hech bo'lmaganda PSQL kabi ACID ma'lumotlar bazasi uchun) tranzaktsiya o'zgartirilayotgan jadvallar va qatorlarda qulflarni ushlab turadi.
  5. Django DB operatsiyasi bajarilganda, ma'lumotlar bazasi mos keladigan qulfni oladi va ushbu jadval yoki qatorda har qanday ziddiyatli operatsiyalarni oldini oladi.
  6. Bu qulfning ochilishini kutish tufayli boshqa ulanishlarni kutish vaqti tugashiga olib kelishi mumkin.
  7. Agar operatsiya bajarilmasa yoki ish vaqti xatosi bo'lsa, JB butun tranzaksiyani orqaga qaytaradi va qulflarni chiqaradi.
  8. Agar butun tranzaksiya muvaffaqiyatli bo'lsa, u holda barcha o'zgarishlar amalga oshiriladi va boshqa JB ulanishlari uchun mavjud bo'ladi.
  9. Qulflar chiqariladi.


Endi biz tranzaktsiyada nima qilish kerakligini va nimadan qochish kerakligini muhokama qilamiz. Quyidagi tranzaksiya xatti-harakatlari tufayli ma'lum operatsiyalar tranzaksiya blokiga joylashtirilganda xavflidir.


  • Tranzaksiya muvaffaqiyatsiz tugamaguncha yoki tugallanmaguncha tranzaktsiyalar qulflarda saqlanadi.
  • Tranzaksiyalar muvaffaqiyatsiz bo'lganda, barcha ma'lumotlar bazasi operatsiyalarini o'zgartiradi.
  • Ma'lumotlar bazasi operatsiyasi bajarilishi bilanoq tranzaktsiyalar blokirovkasini talab qiladi.

TLDR, Xulosa

In

  • JBda qaytariladigan operatsiyalar - Agar JB operatsiyasini qaytarib bo'lmasa va tranzaksiya bajarilmasa, JB yomon holatda qoladi, chunki tranzaksiya o'zgarishlarni avtomatik ravishda orqaga qaytarishga harakat qiladi, lekin ular qaytarib bo'lmaydi, shuning uchun u muvaffaqiyatsiz bo'ladi.
  • JB bo'yicha zarur bo'lgan tegishli operatsiyalar - Biz foydalanuvchi yozuvisiz yangi bank hisob qaydnomasini yarata olmaymiz, shuning uchun ikkalasini ham bitta tranzaksiyada yaratishimiz kerak.
  • Qaytariladigan va tegishli biznes mantig'i - Depozit bilan yangi hisob qaydnomasini yaratgandan so'ng mijozning umumiy balansini hisoblash (hatto buni aqlli modellashtirish va muvofiqlashtirish bilan tranzaktsiyadan olib tashlash mumkin).

Xavfli

  • Sekin so'rovlar - Ushbu uchta stsenariydan tashqari ma'lumotlarni olish odatda tezdir. Ushbu so'rovlar tranzaksiyani sekinlashtiradi va uning qulflangan vaqtini uzaytiradi, bu esa boshqa foydalanuvchilarga salbiy ta'sir ko'rsatadi.
  • Bir nechta jadvallar ustida operatsiyalar - Bir nechta jadvallar ustidagi operatsiyalar bilan tuzilgan tranzaksiya har bir jadvalni bajarilgunga qadar bloklashi mumkin. Bu, ayniqsa, Django migratsiyalarida keng tarqalgan - migratsiyani kichik va bir vaqtning o'zida bir yoki bir nechta jadvallarga yo'naltirishning yana bir sababi.
  • Ma'lumotlarni ko'chirish - tranzaktsiyalar so'rov bajarilgandan so'ng, tranzaksiya bajarilmagan yoki tugaguniga qadar blokirovkada saqlanib qolganligi sababli, jadvalning har bir qatorida ishlaydigan migratsiya har bir satrda o'qish yoki yozishni oldini olish orqali butun jadvalni blokirovka qiladi.
  • (Faqat PSQL va SQLite uchun*) Jadvallar yoki ustunlarni o'zgartirish - bu operatsiyalar blokirovkalarning eng qattiq shaklini talab qiladi va shuning uchun butun jadvalda o'qish/yozishni oldini oladi. Ushbu operatsiyalar uzilishga olib kelishi mumkin.

Chiqib ketdi

  • Qaytarib bo'lmaydigan operatsiyalar - tranzaksiya orqaga qaytarilsa, tranzaksiyadagi hamma narsa qaytarilishi kerak; agar biz tranzaktsiyaga API chaqiruvini qo'ysak, uni qaytarib bo'lmaydi.
  • Qo'ng'iroqlarni bloklash - tranzaksiyalar o'zgaruvchan jadvallar/satrlarda boshqa barcha so'rovlarning ishlashiga to'sqinlik qilganligi sababli, tranzaksiya davomiyligini oshiradigan har qanday kod JB bloklanishiga olib keladi, bu esa JBga bog'liq bo'lgan ilovalarda kutish vaqti va javob bermasligiga olib keladi.


Muqobil variantlar va kod misollari uchun o'qishni davom eting.

Tranzaksiyalar bizning ilovalarimizga qanday zarar etkazishi mumkin?

Birlamchi xavf shundan iboratki, tranzaktsiyalar jadvallar va qatorlarda qarama-qarshi operatsiyalarni oldini olish va tranzaksiyani qaytarib bo'lishiga imkon berish uchun bajarilgunga qadar qulfni ushlab turadi - bu tranzaksiyadagi JB operatsiyalarini atomik qilish uchun zarurdir. Bu shuni anglatadiki, bir nechta jadvallarda yoki bir nechta muhim jadvallarda ishlaydigan uzoq muddatli tranzaksiya blokirovkalash va ushbu jadvallar/satrlarni o'qish/yozishni oldini olish orqali uzilishlarga olib kelishi mumkin.


Aslini olganda, agar biz tranzaksiya blokiga noto'g'ri kod qo'ysak, biz JB bilan boshqa barcha ulanishlarni unda operatsiyalarni amalga oshirishni bloklash orqali JBni samarali ravishda olib tashlashimiz mumkin.


Ikkilamchi tavakkalchilik shundan iboratki, tranzaktsiyalar qaytarilishi kerak va qaytarilishi kutiladi. Agar tranzaktsiyada xatolik yuzaga kelsa, JB avtomatik ravishda har bir operatsiyani o'zgartiradi. Shuning uchun biz tranzaksiyaga kiritgan ma'lumotlar bazasi operatsiyalari qaytarilishi kerak - aksariyat hollarda PSQL bilan bu haqda tashvishlanishga hojat yo'q. Ammo boshqa kodlar haqida nima deyish mumkin?


Ko'pincha ma'lumotlarimizni o'zgartirganimizda, biz voqealarni yoqish, xizmatlarni yangilash, push bildirishnomalarini yuborish va hokazolarni bajarishimiz kerak. Bu vazifalarni qaytarib bo'lmaydi - biz voqea, so'rov yoki bildirishnomani qaytarib bo'lmaydi. Agar xatolik yuz bersa, maʼlumotlar oʻzgarishlari orqaga qaytariladi, lekin biz “Sizning hisobotingiz yaratildi; uni koʻrish uchun shu yerni bosing” degan push-bildirishnomani allaqachon yuborganmiz. Agar foydalanuvchi yoki boshqa xizmatlar ushbu noto'g'ri ma'lumotlar bo'yicha harakat qilsa nima bo'ladi? Muvaffaqiyatsizliklar kaskadi bo'ladi. Shuning uchun, bekor qilib bo'lmaydigan har qanday kod tranzaksiyada bo'lmasligi kerak yoki tranzaksiyada xatolik yuz berganda tizimimizni yomon holatda qoldirish xavfi bor.

In

  • JBda qaytariladigan operatsiyalar - Agar JB operatsiyasini qaytarib bo'lmasa va tranzaksiya bajarilmasa, JB yomon holatda qoladi, chunki tranzaksiya o'zgarishlarni avtomatik ravishda orqaga qaytarishga harakat qiladi, lekin ular qaytarib bo'lmaydi, shuning uchun u muvaffaqiyatsiz bo'ladi.
  • JB bo'yicha zarur bo'lgan tegishli operatsiyalar - Biz foydalanuvchi yozuvisiz yangi bank hisob qaydnomasini yarata olmaymiz, shuning uchun ikkalasini ham bitta tranzaksiyada yaratishimiz kerak.
  • Qaytariladigan va tegishli biznes mantig'i - Depozit bilan yangi hisob qaydnomasini yaratgandan so'ng mijozning umumiy balansini hisoblash (hatto buni aqlli modellashtirish va muvofiqlashtirish bilan tranzaktsiyadan olib tashlash mumkin).

Xavfli

Bular, qancha ma'lumotlar qayta ishlanayotganiga va JB trafigiga qarab, qulflarni juda uzoq vaqt ushlab turish tufayli uzilishlarga olib kelishi mumkin bo'lgan narsalardir. Agar ular uzoq vaqt talab qilmasa, bularning barchasi yaxshi.


  • Sekin so'rovlar - Ushbu uchta stsenariydan tashqari ma'lumotlarni olish odatda tezdir. Ushbu so'rovlar tranzaksiyani sekinlashtiradi va uning qulflangan vaqtini uzaytiradi, bu esa boshqa foydalanuvchilarga salbiy ta'sir ko'rsatadi.

    • Misollar
      • Indekslanmagan ustunlar bo'yicha so'rovlar
      • Katta jadvallardagi so'rovlar
      • Qo'shiladi
     @transaction.atomic def process_large_order_report(start_date, end_date, min_order_value=1000): # Complex query with multiple joins and aggregations large_orders = Order.objects.filter( created_at__range=(start_date, end_date), total_amount__gte=min_order_value, status='completed' ).select_related( 'customer', 'shipping_address', 'billing_address' ).prefetch_related( 'items__product__category', 'items__product__supplier' ).annotate( item_count=Count('items'), total_weight=Sum('items__product__weight'), discount_percentage=F('discount_amount') * 100 / F('total_amount') ).filter( # Additional complex filtering Q(customer__user__is_active=True) & (Q(items__product__category__name='Electronics') | Q(items__product__category__name='Furniture')) & ~Q(shipping_address__country='US') ).order_by('-total_amount') # do the transactional work with the large_orders queryset
    • Muqobil
      • Ushbu so'rovlarni tranzaktsiyadan oldin va undan tashqari bajaring.
 # fixed def process_large_order_report(start_date, end_date, min_order_value=1000): # Complex query with multiple joins and aggregations large_orders = Order.objects.filter( created_at__range=(start_date, end_date), total_amount__gte=min_order_value, status='completed' ).select_related( 'customer', 'shipping_address', 'billing_address' ).prefetch_related( 'items__product__category', 'items__product__supplier' ).annotate( item_count=Count('items'), total_weight=Sum('items__product__weight'), discount_percentage=F('discount_amount') * 100 / F('total_amount') ).filter( # Additional complex filtering Q(customer__user__is_active=True) & (Q(items__product__category__name='Electronics') | Q(items__product__category__name='Furniture')) & ~Q(shipping_address__country='US') ).order_by('-total_amount') # Start the transaction block with transaction.atomic(): # do the transactional work with the large_orders queryset


  • Bir nechta jadvallar ustida operatsiyalar - bir nechta jadvallar ustida operatsiyalar bilan tranzaksiya har bir jadvalni bajarilgunga qadar bloklashi mumkin. Bu, ayniqsa, Django migratsiyalarida keng tarqalgan - migratsiyani kichik va bir vaqtning o'zida bir yoki bir nechta jadvallarga yo'naltirishning yana bir sababi.


    • Misollar
      • Jadval yoki ustun tuzilishini o'zgartirishga qarang
     class Migration(migrations.Migration): dependencies = [("migrations", "0001_initial")] # too many operations operations = [ migrations.RemoveField("Author", "age"), migrations.AddField("Author", "rating", models.IntegerField(default=0)), migrations.AlterField("Book", "price", models.DecimalField(max_digits=5, decimal_places=2)), ]
    • Muqobil
      • Tranzaktsiyani bir nechta kichikroq tranzaktsiyalarga bo'ling va ularni qayta qo'ng'iroqlarga bog'lang.
 # fixed # 1st migration class Migration(migrations.Migration): dependencies = [("migrations", "0001_initial")] operations = [ migrations.RemoveField("Author", "age"), ] # 2nd migration class Migration(migrations.Migration): dependencies = [("migrations", "0002_initial")] operations = [ migrations.AddField("Author", "rating", models.IntegerField(default=0)), ] # 3rd migration class Migration(migrations.Migration): dependencies = [("migrations", "0003_initial")] operations = [ migrations.AlterField("Book", "price", models.DecimalField(max_digits=5, decimal_places=2)), ]


  • Ma'lumotlarni ko'chirish - tranzaktsiyalar so'rov bajarilgandan so'ng tranzaksiya bajarilmagan yoki tugaguniga qadar blokirovkada ushlab turilganligi sababli, jadvaldagi har bir satrda ishlaydigan migratsiya har bir satrda o'qish yoki yozishni oldini olish orqali butun jadvalni blokirovka qiladi.

     def migrate_user_profiles(): # Get all users with legacy profiles users_with_profiles = User.objects.filter( legacy_profile__isnull=False ).select_related('legacy_profile') # Process all users in a single transaction with transaction.atomic(): # Track progress total = users_with_profiles.count() print(f"Migrating {total} user profiles...") # Process each user for i, user in enumerate(users_with_profiles): if i % 100 == 0: print(f"Processed {i}/{total} profiles") legacy = user.legacy_profile legacy.update_new_user_profile()
    • Muqobil
      • Tranzaktsiyani butun migratsiya emas, balki alohida operatsiyalar atrofida o'tkazing. Tranzaktsiyaning har bir qatoriga yangilanishlarni qo'yish orqali biz faqat qisqa vaqt davomida qulflarni ushlab turamiz.
 # fixed def migrate_user_profiles(): # Get all users with legacy profiles users_with_profiles = User.objects.filter( legacy_profile__isnull=False ).select_related('legacy_profile') # Process all users in a single transaction # Track progress total = users_with_profiles.count() print(f"Migrating {total} user profiles...") # Process each user for i, user in enumerate(users_with_profiles): if i % 100 == 0: print(f"Processed {i}/{total} profiles") with transaction.atomic(): legacy = user.legacy_profile legacy.update_new_user_profile()


  • ( Faqat PSQL va SQLite uchun *) Jadvallar yoki ustunlarni o'zgartirish - bu operatsiyalar eng qattiq blokirovka shaklini talab qiladi va shuning uchun butun jadvalda o'qish/yozishni oldini oladi. Ushbu operatsiyalar uzilishga olib kelishi mumkin.
    • Misol
      • Ustunni o'zgartirish
      • Jadvalni o'zgartirish
    • Muqobil
      • Ularni keyinroq ishga tushiring. Bu soʻrovlar zarur, lekin biz ularni ish vaqtida bajarishimiz shart emas. Bu erda eng yaxshi siyosat jadvalning qanchalik muhimligini aniqlash, migratsiya qancha davom etishini taxmin qilish, JB eng kam trafikga ega bo'lganda migratsiyani amalga oshirish va orqaga qaytish rejasini tayyorlash orqali uzilish xavfini kamaytirishdir.

      • Tranzaktsiyaga ketadigan vaqtni qisqartiring. Buni jadvalni qismlarga bo'lish va alohida bo'limlarda migratsiyani amalga oshirish orqali amalga oshirish mumkin. PSQL bo'limlari va Django


*Django faqat PSQL va SQLite uchun migratsiya atrofidagi tranzaktsiyalarni o'rab oladi.

 class Migration(migrations.Migration): dependencies = [("migrations", "0001_initial")] # this migration, if on a large table, can slow down and block other operations # do it later operations = [ migrations.RemoveField("Users", "middle_name"), ]


Chiqib ketdi

  • Qaytarib bo'lmaydigan operatsiyalar - tranzaksiya orqaga qaytarilsa, tranzaksiyadagi hamma narsa qaytarilishi kerak; agar biz tranzaktsiyaga API chaqiruvini qo'ysak, uni qaytarib bo'lmaydi.

    • Misollar
      • Navbatga voqea qo'shish — boshqa hodisalarni ishga tushirish
      • API chaqiruvini yuborish — holat yangilanishlari, ishga tushirish ishlari va h.k.
     def transaction(user_data, user_files): with transaction.atomic(): user = User.objects.create(**user_data) async_notification_service.send_email(user.email, "You can login now!") Account.objects.create(user=user, balance=0) # rest of user creation proccess
    • Alternativlar
      • Tranzaktsiyani qayta qo'ng'iroq qilishda ro'y berishi kerak bo'lgan muhim biznes mantig'ini bajaring - Oncommit qayta qo'ng'iroq DOIMA tranzaksiya muvaffaqiyatli bo'lgandan keyin chaqiriladi va tranzaksiyadagi barcha yangilanishlar oncommit qayta qo'ng'iroqda mavjud.
      • Shuningdek, biz operatsiyani teskari qilishimiz mumkin, ya'ni voqealarni o'chirish yoki bekor qilish API qo'ng'irog'ini yuborish usulini yaratishimiz mumkin — Bu voqea navbati yoki APIga ega bo'lgan jamoa uchun ahamiyatsiz vazifadir. Men buni tavsiya qilmayman.
 def transaction(user_data, user_files): with transaction.atomic(): user = User.objects.create(**user_data) Account.objects.create(user=user, balance=0) # rest of user creation proccess # the transaction is still in progress, so it can still be rolled back, it is not # committed until the transaction block is exited, so putting the notification here # is not a good idea - especially if the job starts immediately tries to read the data # this creates a race condition async_notification_service.send_email(user.email, "You can login now!") def transaction(user_data, user_files): with transaction.atomic(): user = User.objects.create(**user_data) Account.objects.create(user=user, balance=0) # rest of user creation proccess transaction.on_commit(partial(async_notification_service.send_email, user.email, "You can login now!"))


  • Qo'ng'iroqlarni bloklash — tranzaksiyalar o'zgaruvchan jadvallar/satrlar bo'yicha boshqa barcha so'rovlarning ishlashiga to'sqinlik qilganligi sababli, tranzaksiya davomiyligini oshiradigan har qanday kod JB bloklanishiga olib keladi, bu esa JBga bog'liq bo'lgan ilovalarda kutish vaqti va javob bermasligiga olib keladi.


    • Misollar
      • Tarmoq qo'ng'iroqlari - tranzaktsiyaga kiritiladigan ma'lumotlarni olish uchun API-larga so'rovlar yuborish.
      • Jurnalga ro'yxatdan o'tish biz foydalanadigan loggerga qarab, biz tranzaktsiyada bo'lganimizda, kutubxona jurnallarni yuborishi mumkin yoki agar biz datadog-dan foydalanayotgan bo'lsak, u jurnallarni saqlashning boshqa jarayoniga ega bo'ladi, lekin biz hali ham jurnallarni to'liq ish ularni faylga saqlaguncha xotirada saqlash narxini to'laymiz.
      • Disk operatsiyalari - jadvalga kiritish uchun CSV ni yuklash yoki jadvalni CSV ga eksport qilish.
      • Protsessorning og'ir vazifalari - Matritsani ko'paytirish yoki har qanday og'ir matematik/ma'lumotlarni o'zgartirish protsessorni va boshqa barcha operatsiyalarni bloklaydi - Python's Global Interpreter Lock har bir ipni CPUdan bir vaqtning o'zida foydalanishga majbur qiladi va Django bir marta qayta ishlanadi (tranzaksiyadagi har bir operatsiya ketma-ket amalga oshiriladi).
     def transaction(user_data, user_files): with transaction.atomic(): user = User.objects.create(**user_data) for file_data in user_files: # transaction waits for this upload and so do all other connections that need access to table/rows the transaction # uses url = Cloudinary.upload_file(file_data['data']) Files.objects.create(**file_data['meta_data'], user=user, url=url) Account.objects.create(user=user, balance=0) # rest of user creation proccess
    • Alternativlar
      • Tranzaktsiyadan oldin ma'lumotlarni tayyorlang - Disk/tarmoq ma'lumotlarini oldindan yuklang. Ma'lumotlar tayyor bo'lgach, u bilan operatsiyani bajaring.
      • To'ldiruvchi ma'lumotlardan foydalanish - Osonlik bilan olinadigan va aniqlanishi mumkin bo'lgan aniq to'ldiruvchi ma'lumotlar to'plamini yarating (uni ishlab chiqarish ma'lumotlari bilan xato qilishning iloji yo'q). Tranzaktsiyadan oldin uni yuklang va undan foydalaning.
      • Ma'lumotlarni yaratish - Agar to'ldiruvchi ma'lumotlardan foydalanishga to'sqinlik qiladigan maydonlarda noyoblik cheklovlari mavjud bo'lsa.
      • Bu xavfli - bu psevdo-tasodifiy algoritmlarning tabiati tufayli oldindan aytib bo'lmaydigan muvaffaqiyatsizlikka olib keladi - shuning uchun kutilmagan muvaffaqiyatsizlikka yo'l qo'ymaslik uchun yaxshi urug' bilan yaxshi tasodifiy algoritmdan foydalaning.
      • Cheklovlarni olib tashlang yoki o'zgartiring - Agar cheklovlar bizga yozuvlarimizni xavfsiz yaratishga imkon bermasa, sxemamizda muammo bor. Cheklovlarni yozuv qachon tugallanishi va kuzatilishi kerakligini ko'rsatadigan holat ustuniga bog'liq qilib qo'ying.
 # not bad def transaction(user_data, user_files): user = None with transaction.atomic(): user = User.objects.create(**user_data) Account.objects.create(user=user, balance=0) # rest of user creation proccess for file_data in user_files: url = Cloudinary.upload_file(file_data['data']) Files.objects.create(**file_data['meta_data'], user=user, url=url) # best fix from functools import partial def transaction(user_data, user_files): user = None with transaction.atomic(): user = User.objects.create(**user_data) Account.objects.create(user=user, balance=0) # rest of user creation proccess # partials create a callable with the function and arguments # so that the function is called with the arguments when the transaction is committed # TODO: diff between partial and lambda here??? transaction.on_commit(partial(create_user_files, user_files, user)) def create_user_files(user_files, user): for file_data in user_files: url = Cloudinary.upload_file(file_data['data']) Files.objects.create(**file_data['meta_data'], user=user, url=url)


Keyingi - PSQL buyruqlari bir-birini qanday bloklaydi

Keyingi postda biz PSQL-ga sho'ng'iymiz va quyidagilarni bilib olamiz:

  • Turli xil buyruqlar jadval va qatorlarni qanday bloklaydi
  • Qaysi buyruqlarni bajarish eng xavfli hisoblanadi

Manbalar

  • Atom
  • Django migratsiyalari va operatsiyalari
    • DDL tranzaksiyalarini (SQLite va PostgreSQL) qo'llab-quvvatlaydigan ma'lumotlar bazalarida barcha migratsiya operatsiyalari sukut bo'yicha bitta tranzaksiya ichida ishlaydi. Aksincha, agar ma'lumotlar bazasi DDL tranzaksiyalarini (masalan, MySQL, Oracle) qo'llab-quvvatlamasa, barcha operatsiyalar tranzaksiyasiz ishlaydi.
    • Atom atributini False ga o'rnatish orqali tranzaktsiyada migratsiyani amalga oshirishni oldini olishingiz mumkin. Masalan:
    • Shuningdek, tranzaksiya ichidagi migratsiya qismlarini atomic() yordamida yoki atomic=True ni RunPython ga o‘tkazish orqali amalga oshirish mumkin.
  • PSQL bo'limlari va Django
    • Django-ning ORM-da bo'lingan jadvallar uchun o'rnatilgan yordam mavjud emas, shuning uchun agar siz ilovangizda bo'limlardan foydalanmoqchi bo'lsangiz, bu biroz qo'shimcha ish talab qiladi.
    • Bo'limlardan foydalanishning bir usuli - xom SQL-ni ishlatadigan o'z migratsiyalaringizni aylantirishdir. Bu ishlaydi, lekin kelajakda jadvalga kiritadigan barcha o'zgarishlar uchun migratsiyalarni qo'lda boshqarishingiz kerak bo'ladi.
    • Yana bir variant - django-postgres-extra deb nomlangan paketdan foydalanish. Django-postgres-extra, Django-ning ORM-ga o'rnatilmagan bir nechta PostgreSQL funksiyalarini qo'llab-quvvatlaydi, masalan, TRUNCATE TABLE va jadvallarni qismlarga ajratish.
  • PSQL operatsiyalari
  • Python: Django tranzaksiyalari qanday ishlaydi


L O A D I N G
. . . comments & more!

About Author

Michael T. Andemeskel HackerNoon profile picture
Michael T. Andemeskel@mta
I write code and, occasionally, bad poetry. Thankfully, my code isn’t as bad as my poetry.

TEGI QILISH

USHBU MAQOLA TAQDIM ETILGAN...