2012-06-26 96 views
1

DB插入Django的奇怪行为我有一个简单的测试案例在Django失败:从单独的线程

模型(应用程序/ models.py):

from django.db import models 
class M(models.Model): 
    condition = models.CharField(max_length=80, db_index=True) 

测试(应用/ tests.py) :

from django.test import TestCase 
import threading 
import time 
from app.models import M 

def insert(): 
    time.sleep(0.3) 
    ua = M(condition='x') 
    ua.save() 

class DjangoRaceTest(TestCase): 
    def test_parallel(self): 
     insert() # <--- works 
     #threading.Thread(target=insert).start() # <-- fails 

     for i in range(10): 
      count = M.objects.all() 
      if count: 
       return True 
      time.sleep(0.1) 

     assert count 

上面的代码通过;但如果我注释掉直接调用插入,而是取消对线程调用,则断言失败,我也得到:

Creating test database for alias 'default'... 
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/jacobsen/testdjango/app/tests.py", line 10, in insert 
    ua.save() 
    File "/home/jacobsen/dj14/lib/python2.6/site-packages/Django-1.4-py2.6.egg/django/db/models/base.py", line 463, in save 
    self.save_base(using=using, force_insert=force_insert, force_update=force_update) 
    File "/home/jacobsen/dj14/lib/python2.6/site-packages/Django-1.4-py2.6.egg/django/db/models/base.py", line 551, in save_base 
    result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw) 
    File "/home/jacobsen/dj14/lib/python2.6/site-packages/Django-1.4-py2.6.egg/django/db/models/manager.py", line 203, in _insert 
    return insert_query(self.model, objs, fields, **kwargs) 
    File "/home/jacobsen/dj14/lib/python2.6/site-packages/Django-1.4-py2.6.egg/django/db/models/query.py", line 1576, in insert_query 
    return query.get_compiler(using=using).execute_sql(return_id) 
    File "/home/jacobsen/dj14/lib/python2.6/site-packages/Django-1.4-py2.6.egg/django/db/models/sql/compiler.py", line 910, in execute_sql 
    cursor.execute(sql, params) 
    File "/home/jacobsen/dj14/lib/python2.6/site-packages/Django-1.4-py2.6.egg/django/db/backends/sqlite3/base.py", line 337, in execute 
    return Database.Cursor.execute(self, query, params) 
DatabaseError: no such table: app_m 

很明显,有一些神奇的Django没有我在这里,还是......什么?我已经在OS X,Ubuntu 10.04,Django 1.2和1.4的各种组合上测试过了。

回答

2

答案似乎是内存sqlite数据库不能跨线程共享。

This is a bug report from 1.1,其中一个核心开发者断定它不是基于SQLAlchemy's lack of support为它的错误(在没有从源码引用其他直接信息):

Pysqlite连接不支持被线程之间移动, 除非check_same_thread Pysqlite标志被设置为False。另外,在使用内存中的SQLite数据库时,完整数据库 仅存在于单个连接的范围内。据报道, 内存数据库不支持在线程间共享 线程,而不考虑check_same_thread标志 - 这意味着多线程应用程序不能跨线程共享来自内存:数据库 的数据,除非对连接的访问​​是有限的到单个的 工作线程,它通过排队机制与 并发线程通信。