Tôi đang làm việc trong một ứng dụng web Django cần truy vấn cơ sở dữ liệu PostgreSQL. Khi triển khai đồng thời sử dụng giao diện Python threading, tôi nhận được lỗi DoesNotExist
cho các mục được truy vấn. Tất nhiên, những lỗi này không xảy ra khi thực hiện truy vấn tuần tự.Lỗi cơ sở dữ liệu ở Django khi sử dụng luồng
Hãy để tôi thể hiện một thử nghiệm đơn vị mà tôi đã viết để chứng minh hành vi bất ngờ:
class ThreadingTest(TestCase):
fixtures = ['demo_city',]
def test_sequential_requests(self):
"""
A very simple request to database, made sequentially.
A fixture for the cities has been loaded above. It is supposed to be
six cities in the testing database now. We will made a request for
each one of the cities sequentially.
"""
for number in range(1, 7):
c = City.objects.get(pk=number)
self.assertEqual(c.pk, number)
def test_threaded_requests(self):
"""
Now, to test the threaded behavior, we will spawn a thread for
retrieving each city from the database.
"""
threads = []
cities = []
def do_requests(number):
cities.append(City.objects.get(pk=number))
[threads.append(threading.Thread(target=do_requests, args=(n,))) for n in range(1, 7)]
[t.start() for t in threads]
[t.join() for t in threads]
self.assertNotEqual(cities, [])
Như bạn thấy, thử nghiệm đầu tiên thực hiện một số yêu cầu cơ sở dữ liệu liên tục, được thực sự làm việc với không có vấn đề. Tuy nhiên, thử nghiệm thứ hai thực hiện chính xác các yêu cầu tương tự nhưng mỗi yêu cầu được sinh ra trong một luồng. Điều này thực sự không thành công, trả về một ngoại lệ DoesNotExist
.
Kết quả của việc thực hiện các đơn vị kiểm tra này là như thế này:
test_sequential_requests (cesta.core.tests.threadbase.ThreadingTest) ... ok
test_threaded_requests (cesta.core.tests.threadbase.ThreadingTest) ...
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python2.6/threading.py", line 532, in __bootstrap_inner
self.run()
File "/usr/lib/python2.6/threading.py", line 484, in run
self.__target(*self.__args, **self.__kwargs)
File "/home/jose/Work/cesta/trunk/src/cesta/core/tests/threadbase.py", line 45, in do_requests
cities.append(City.objects.get(pk=number))
File "/home/jose/Work/cesta/trunk/parts/django/django/db/models/manager.py", line 132, in get
return self.get_query_set().get(*args, **kwargs)
File "/home/jose/Work/cesta/trunk/parts/django/django/db/models/query.py", line 349, in get
% self.model._meta.object_name)
DoesNotExist: City matching query does not exist.
... đề khác trả về một kết quả tương tự ...
Exception in thread Thread-6:
Traceback (most recent call last):
File "/usr/lib/python2.6/threading.py", line 532, in __bootstrap_inner
self.run()
File "/usr/lib/python2.6/threading.py", line 484, in run
self.__target(*self.__args, **self.__kwargs)
File "/home/jose/Work/cesta/trunk/src/cesta/core/tests/threadbase.py", line 45, in do_requests
cities.append(City.objects.get(pk=number))
File "/home/jose/Work/cesta/trunk/parts/django/django/db/models/manager.py", line 132, in get
return self.get_query_set().get(*args, **kwargs)
File "/home/jose/Work/cesta/trunk/parts/django/django/db/models/query.py", line 349, in get
% self.model._meta.object_name)
DoesNotExist: City matching query does not exist.
FAIL
======================================================================
FAIL: test_threaded_requests (cesta.core.tests.threadbase.ThreadingTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/jose/Work/cesta/trunk/src/cesta/core/tests/threadbase.py", line 52, in test_threaded_requests
self.assertNotEqual(cities, [])
AssertionError: [] == []
----------------------------------------------------------------------
Ran 2 tests in 0.278s
FAILED (failures=1)
Destroying test database for alias 'default' ('test_cesta')...
Hãy nhớ rằng tất cả điều này là xảy ra trong cơ sở dữ liệu PostgreSQL, được cho là luồng an toàn, không phải với SQLite hoặc similars. Kiểm tra đã được chạy bằng cách sử dụng PostgreSQL cũng.
Tại thời điểm này, tôi hoàn toàn bị mất về những gì có thể không thành công. Bất kỳ ý tưởng hoặc đề nghị?
Cảm ơn!
EDIT: Tôi đã viết một chế độ xem nhỏ chỉ để kiểm tra xem nó có hoạt động không. Đây là mã của quan điểm:.
def get_cities(request):
queue = Queue.Queue()
def get_async_cities(q, n):
city = City.objects.get(pk=n)
q.put(city)
threads = [threading.Thread(target=get_async_cities, args=(queue, number)) for number in range(1, 5)]
[t.start() for t in threads]
[t.join() for t in threads]
cities = list()
while not queue.empty():
cities.append(queue.get())
return render_to_response('async/cities.html', {'cities': cities},
context_instance=RequestContext(request))
(Xin vui lòng, không đưa vào tài khoản các sự điên rồ của văn bản cho logic ứng dụng bên trong mã xem Hãy nhớ rằng đây chỉ là một bằng chứng của khái niệm và sẽ không bao giờ trong ứng dụng thực tế)
Kết quả là mã đang hoạt động tốt, các yêu cầu được thực hiện thành công trong chuỗi và cuối cùng hiển thị các thành phố sau khi gọi URL của nó.
Vì vậy, tôi nghĩ việc tạo truy vấn bằng cách sử dụng chuỗi sẽ chỉ là vấn đề khi bạn cần kiểm tra mã. Trong sản xuất, nó sẽ làm việc mà không có bất kỳ vấn đề.
Bất kỳ đề xuất hữu ích nào để kiểm tra loại mã này thành công?
Bạn có chắc chắn là vật cố được nhập không? Bạn có thể dán nhật ký ghi: "Lịch thi đấu demo_city được xử lý" hay thứ gì đó như thế ...... Ah, nevermind .. chưa đọc hết câu hỏi .. – Tisho