How to do table / row locks in Django

In production environments where Django runs on Apache or with several Gunicorn employees, it is at risk of concurrency problems.

Thus, I was very surprised to find that Django ORM does not explicitly support table / row locking. It supports transactions very widely, but it only solves half of the concurrency problem.

With MySQL backend, what is the proper way to do a lock in Django? Or is there something else in the game in the Django environment that makes them unnecessary?

+5
source share
2 answers

Django does not explicitly provide an API to do table locking. In my experience, well-designed code rarely requires locking the entire table, and most concurrency problems can be solved with row-level locking. This is the last effort: it does not solve concurrency, it just kills any attempt in concurrency.

If you really need a table-level lock, you can use the cursor and execute raw SQL statements:

from django.db import connection with connection.cursor() as cursor: cursor.execute("LOCK TABLES %s READ", [tablename]) try: ... finally: cursor.execute("UNLOCK TABLES;") 
+8
source

Consider setting the transaction isolation level to the serializable version and using a MySQL table type that supports transactions (MyISAM does not, InnoDB does).

After you make sure you have a backend that supports transactions, you need to disable autocommit ( https://docs.djangoproject.com/en/1.8/topics/db/transactions/#autocommit-details ), and then make sure your code issues the appropriate commit statement or rollback at the end of what you consider transactions.

There is an example or two in the above documents.

It takes a little more work and attention, but you will get transactions.

0
source

Source: https://habr.com/ru/post/1235888/


All Articles