Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Transaction_Behavior_in_Django.pdf

tim
April 25, 2019

 Transaction_Behavior_in_Django.pdf

tim

April 25, 2019
Tweet

More Decks by tim

Other Decks in Technology

Transcript

  1. Django ORM In A Glance • Access DB row like

    an simple object • obj.attribute, • obj.save() • Aware of Relational DB’s Advantage • Use Transaction to support Atomic and Isolation
  2. Transaction • Within transaction • You can rollback your data

    while meets problem • You can isolate what you see and what you write
  3. However • Default isolation level is read committed. • PostgreSQL

    default use auto-commit mode + read commiteed(So As Django)
  4. The problem is • Your logic base on first query’s

    result but it will be changed latter
  5. Show Me The Code counter = 0 # logically we

    would like a infinite retry. but infinite is too scaring while counter < 1000: counter += 1 try: with transaction.atomic(): cursor = connections[‘your_db’].cursor() cursor.execute('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE') # Your DB Operations except OperationalError: time.sleep(counter) # to avoid retry in a very short interval continue 1 2 3
  6. Show Me The Code counter = 0 # logically we

    would like a infinite retry. but infinite is too scaring while counter < 1000: counter += 1 try: with transaction.atomic(): cursor = connections[‘your_db’].cursor() cursor.execute('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE') # Your DB Operations except OperationalError: time.sleep(counter) # to avoid retry in a very short interval continue 1 2 3 1 the context manager will start a transaction and commit after exists the block
  7. Show Me The Code counter = 0 # logically we

    would like a infinite retry. but infinite is too scaring while counter < 1000: counter += 1 try: with transaction.atomic(): cursor = connections[‘your_db’].cursor() cursor.execute('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE') # Your DB Operations except OperationalError: time.sleep(counter) # to avoid retry in a very short interval continue 1 2 3 2 change the isolation level to serializable
  8. Show Me The Code counter = 0 # logically we

    would like a infinite retry. but infinite is too scaring while counter < 1000: counter += 1 try: with transaction.atomic(): cursor = connections[‘your_db’].cursor() cursor.execute('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE') # Your DB Operations except OperationalError: time.sleep(counter) # to avoid retry in a very short interval continue 1 2 3 3 latter transaction will meets Operational Error, usually it needs retry
  9. • Distinguish different lock with different lock id lock_id =

    "Any String You Want" with advisory_lock(lock_id=lock_id, shared=False): pass # Your DB Operations Here
  10. • advisory_lock is a third party package. • https://django-mysql.readthedocs.io/en/latest/locks.html •

    https://github.com/Xof/django-pglocks lock_id = "Any String You Want" with advisory_lock(lock_id=lock_id, shared=False): pass # Your DB Operations Here
  11. Conclusion • The default parameter for Django may not fit

    the strict requirement of concurrency • Read about isolation and atomic concept for a complex application
  12. Reference • Advisory locks https://learning.oreilly.com/library/view/ mastering-postgresql-96/9781783555352/cd02e6cb- 53c6-4bfc-8b12-b7cbb6e6dda7.xhtml • Isolation level

    https://learning.oreilly.com/library/view/ postgresql-development-essentials/9781783989003/ ch05.html • Yuren 好⽂文 https://medium.com/getamis/database- transaction-isolation-a1e448a7736e