Opened 8 years ago

Closed 8 years ago

#27288 closed Uncategorized (invalid)

In multi-db setup changes written to master are not seen on read-replicas

Reported by: Jose M Herrero Owned by: nobody
Component: Testing framework Version: 1.10
Severity: Normal Keywords: multi-db dbrouter
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I'm triying to implement a multi-db platform with one master and some read-replicas, I wanted to reflect this structure also in tests.
I'm following documentation at https://docs.djangoproject.com/es/1.10/topics/db/multi-db/ and https://docs.djangoproject.com/en/1.10/topics/testing/advanced/#tests-and-multiple-databases
A simple test writing and reading back the object fails. (I have used a user with write permissions to avoid problem #27286)

To reproduce with nothing interfering I started a fresh project, these are the steps to reproduce:

  1. Start a new Django 1.10.1 project with django-admin startproject mysite and cd into it cd mysite
  2. Create a database router mysite/dbrouter.py

    Code highlighting:

    class DbRouter(object):
        def db_for_read(self, model, **hints):
            return 'read_replica'
    
        def db_for_write(self, model, **hints):
            return 'default'
    
        def allow_relation(self, obj1, obj2, **hints):
            return True
    
        def allow_migrate(self, db, app_label, model_name=None, **hints):
            if db == 'read_replica':
                return False
            return True
    
  1. Edit mysite.settings.py with master and read databases and set the database router

Code highlighting:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mysite',
        'USER': 'myuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': '',
    },
    'read_replica': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mysite',
        'USER': 'myuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': '',
        'TEST': {
            'MIRROR': 'default',
        },

    },
}
DATABASE_ROUTERS = ['mysite.dbrouter.DbRouter']
  1. Create mysite/tests.py

    Code highlighting:

    from django.test import TestCase
    from django.contrib.auth.models import User
    
    class SurveyFormTest(TestCase):
        def setUp(self):
            self.user = User.objects.create_user('username')
    
        def test_sample(self):
            self.assertEqual(User.objects.count(), 1)
    
  2. Execute the tests and bang! python manage.py test mysite
Creating test database for alias 'default'...
F
======================================================================
FAIL: test_sample (mysite.tests.SurveyFormTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/chemary/workspace/myvirtualenv/mysite/mysite/tests.py", line 9, in test_sample
    self.assertEqual(User.objects.count(), 1)
AssertionError: 0 != 1

----------------------------------------------------------------------
Ran 1 test in 0.111s

FAILED (failures=1)
Destroying test database for alias 'default'...

Change History (2)

comment:1 by Jose M Herrero, 8 years ago

Using TransactionTestCase solves the problem, maybe multi-db in tests is only intended to test that replication configuration works and not the whole set of tests?

Last edited 8 years ago by Jose M Herrero (previous) (diff)

comment:2 by Simon Charette, 8 years ago

Resolution: invalid
Status: newclosed

It looks like you didn't set the multi_db attribute on your test case class.

Please don't use the ticket system as a support channel, see TicketClosingReasons/UseSupportChannels.

Note: See TracTickets for help on using tickets.
Back to Top