Your SlideShare is downloading. ×
Transakcyjność w django
Transakcyjność w django
Transakcyjność w django
Transakcyjność w django
Transakcyjność w django
Transakcyjność w django
Transakcyjność w django
Transakcyjność w django
Transakcyjność w django
Transakcyjność w django
Transakcyjność w django
Transakcyjność w django
Transakcyjność w django
Transakcyjność w django
Transakcyjność w django
Transakcyjność w django
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Transakcyjność w django

214

Published on

Published in: Technology, Design
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
214
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
1
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Transakcyjność w Django Marcin Baran @Sharpekk internetowykantor.pl
  • 2. Zagnieżdżone transakcje
  • 3. W pewnej aplikacji w Django.. @transaction.commit_on_success def run(): Counter.objects.update(views= 1) foo() bar() @transaction.commit_on_success def foo(): Counter.objects.update(views= 2) @transaction.commit_on_success def bar(): Counter.objects.update(views= 3) BEGIN UPDATE "bar_counter" SET "views" = 1 UPDATE "bar_counter" SET "views" = 2 COMMIT BEGIN UPDATE "bar_counter" SET "views" = 3 COMMIT
  • 4. #HEHESZKA ;-) BEGIN UPDATE "bar_counter" SET "views" = 1 UPDATE "bar_counter" SET "views" = 2 COMMIT BEGIN UPDATE "bar_counter" SET "views" = 3 COMMIT
  • 5. @commit_on_success_unless_managed @commit_on_success_unless_managed def run(): Counter.objects.update(views= 1) foo() bar() @commit_on_success_unless_managed def foo(): Counter.objects.update(views= 2) @commit_on_success_unless_managed def bar(): Counter.objects.update(views= 3) BEGIN UPDATE "bar_counter" SET "views" = 1 UPDATE "bar_counter" SET "views" = 2 UPDATE "bar_counter" SET "views" = 3 COMMIT
  • 6. Race Condition Counter.objects.update(views= 1) # Watęk A (w tym samym czasie) # Watęk B (w tym samym czasie) counter = Counter.objects.get(pk= 1) counter = Counter.objects.get(pk= 1) counter.views += 1 counter.save() print Couter.objects.get(pk= 1).counter >>> 2 counter.views += 1 counter.save()
  • 7. SELECT … FOR UPDATE print Counter.objects.update(views= 1) # Watęk A counter = Counter.objects. select_for_update().get(pk= 1) time.sleep( 100) counter.views += 1 counter.save() # Watęk B (+2 po Wątku B) counter = Counter.objects. select_for_update().get(pk= 1) counter.views += 1 counter.save()
  • 8. SELECT … FOR UPDATE ● select_for_update tylko gdy będzie update ● w django od wersji 1.4 ● lub na podstawie snippeta https: //djangosnippets.org/snippets/2766/ w django < 1.4
  • 9. Co jest nie tak z .save() W pewnym frameworku podczas logowania… # django/contrib/auth/models.py def update_last_login(sender, user, **kwargs): user.last_login = timezone.now() user.save() UPDATE `auth_user` SET `username` = %s, `first_name` = %s, `last_name` = %s, `email` = %s, `password` = %s, `is_staff` = %s, `is_active` = %s, `is_superuser` = %s, `last_login` = %s, `date_joined` = %s WHERE `auth_user`.`id` = %s
  • 10. Dlaczego taki save jest zły ? ● brak kontroli nad tym co jest zapisywane do bazy ● wydajność bazy danych ● nadpisywanie zmian (cudzych) ● utrudnia debugowanie - serio! ● django.admin :(
  • 11. Model.save (the right way) ● Użycie save(update_fields=[..]) - trudne w utrzymaniu! ● Użycie django-dirtyfields + własny save ● Własny update(field=val,..)
  • 12. TransactionMiddleware (depercated) It works like this: When a request starts, Django starts a transaction. If the response is produced without problems, Django commits any pending transactions docs.djangoproject.com
  • 13. TransactionMiddleware def home(request): Counter.objects.update(views= 1) foo() bar() @transaction.commit_on_success def foo(): Counter.objects.update(views= 2) @transaction.commit_on_success def bar(): Counter.objects.update(views= 3) raise ValueError BEGIN UPDATE "bar_counter" SET "views" = 1 UPDATE "bar_counter" SET "views" = 2 COMMIT BEGIN UPDATE "bar_counter" SET "views" = 3 ROLLBACK
  • 14. Testy w Django ● domyślnie TestCase nie działa transakcyjnie! ● TransactionTestCase gdy testujemy kod transakcyjny ● Jak testować transakcyjność?
  • 15. Pytania ? kontakt@marcinbaran.be
  • 16. Dziękuje za uwagę!

×