Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
D
django
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
django
Commits
73a57b06
Kaydet (Commit)
73a57b06
authored
May 20, 2014
tarafından
Flavio Curella
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
replaced occurrences of master/slave terminology with leader/follower
üst
a5f6cbce
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
81 additions
and
81 deletions
+81
-81
settings.txt
docs/ref/settings.txt
+3
-3
cache.txt
docs/topics/cache.txt
+9
-9
multi-db.txt
docs/topics/db/multi-db.txt
+30
-30
advanced.txt
docs/topics/testing/advanced.txt
+18
-18
test_operations.py
tests/migrations/test_operations.py
+1
-1
routers.py
tests/multiple_database/routers.py
+1
-1
tests.py
tests/multiple_database/tests.py
+19
-19
No files found.
docs/ref/settings.txt
Dosyayı görüntüle @
73a57b06
...
...
@@ -649,10 +649,10 @@ Default: ``None``
The alias of the database that this database should mirror during
testing.
This setting exists to allow for testing of
master/slave
This setting exists to allow for testing of
leader/follower
configurations of multiple databases. See the documentation on
:ref:`testing
master/slave
configurations
<topics-testing-
masterslave
>` for details.
:ref:`testing
leader/follower
configurations
<topics-testing-
leaderfollower
>` for details.
.. setting:: TEST_NAME
...
...
docs/topics/cache.txt
Dosyayı görüntüle @
73a57b06
...
...
@@ -222,29 +222,29 @@ won't appear in the models cache, but the model details can be used
for routing purposes.
For example, the following router would direct all cache read
operations to ``cache_
slave
``, and all write operations to
``cache_
mast
er``. The cache table will only be synchronized onto
``cache_
mast
er``::
operations to ``cache_
follower
``, and all write operations to
``cache_
lead
er``. The cache table will only be synchronized onto
``cache_
lead
er``::
class CacheRouter(object):
"""A router to control all database cache operations"""
def db_for_read(self, model, **hints):
"All cache read operations go to the
slave
"
"All cache read operations go to the
follower
"
if model._meta.app_label in ('django_cache',):
return 'cache_
slave
'
return 'cache_
follower
'
return None
def db_for_write(self, model, **hints):
"All cache write operations go to
mast
er"
"All cache write operations go to
lead
er"
if model._meta.app_label in ('django_cache',):
return 'cache_
mast
er'
return 'cache_
lead
er'
return None
def allow_migrate(self, db, model):
"Only install the cache model on
mast
er"
"Only install the cache model on
lead
er"
if model._meta.app_label in ('django_cache',):
return db == 'cache_
mast
er'
return db == 'cache_
lead
er'
return None
If you don't specify routing directions for the database cache model,
...
...
docs/topics/db/multi-db.txt
Dosyayı görüntüle @
73a57b06
...
...
@@ -197,17 +197,17 @@ Using routers
Database routers are installed using the :setting:`DATABASE_ROUTERS`
setting. This setting defines a list of class names, each specifying a
router that should be used by the
mast
er router
router that should be used by the
lead
er router
(``django.db.router``).
The
mast
er router is used by Django's database operations to allocate
The
lead
er router is used by Django's database operations to allocate
database usage. Whenever a query needs to know which database to use,
it calls the
mast
er router, providing a model and a hint (if
it calls the
lead
er router, providing a model and a hint (if
available). Django then tries each router in turn until a database
suggestion can be found. If no suggestion can be found, it tries the
current ``_state.db`` of the hint instance. If a hint instance wasn't
provided, or the instance doesn't currently have database state, the
mast
er router will allocate the ``default`` database.
lead
er router will allocate the ``default`` database.
An example
----------
...
...
@@ -225,16 +225,16 @@ An example
introduce referential integrity problems that Django can't
currently handle.
The
master/slave
configuration described is also flawed -- it
The
leader/follower
configuration described is also flawed -- it
doesn't provide any solution for handling replication lag (i.e.,
query inconsistencies introduced because of the time taken for a
write to propagate to the
slave
s). It also doesn't consider the
write to propagate to the
follower
s). It also doesn't consider the
interaction of transactions with the database utilization strategy.
So - what does this mean in practice? Let's consider another sample
configuration. This one will have several databases: one for the
``auth`` application, and all other apps using a
master/slave
setup
with two read
slave
s. Here are the settings specifying these
``auth`` application, and all other apps using a
leader/follower
setup
with two read
follower
s. Here are the settings specifying these
databases::
DATABASES = {
...
...
@@ -244,20 +244,20 @@ databases::
'USER': 'mysql_user',
'PASSWORD': 'swordfish',
},
'
mast
er': {
'NAME': '
mast
er',
'
lead
er': {
'NAME': '
lead
er',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'spam',
},
'
slave
1': {
'NAME': '
slave
1',
'
follower
1': {
'NAME': '
follower
1',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'eggs',
},
'
slave
2': {
'NAME': '
slave
2',
'
follower
2': {
'NAME': '
follower
2',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'bacon',
...
...
@@ -309,30 +309,30 @@ send queries for the ``auth`` app to ``auth_db``::
return None
And we also want a router that sends all other apps to the
master/slave configuration, and randomly chooses a slave
to read
leader/follower configuration, and randomly chooses a follower
to read
from::
import random
class
MasterSlave
Router(object):
class
LeaderFollower
Router(object):
def db_for_read(self, model, **hints):
"""
Reads go to a randomly-chosen
slave
.
Reads go to a randomly-chosen
follower
.
"""
return random.choice(['
slave1', 'slave
2'])
return random.choice(['
follower1', 'follower
2'])
def db_for_write(self, model, **hints):
"""
Writes always go to
mast
er.
Writes always go to
lead
er.
"""
return '
mast
er'
return '
lead
er'
def allow_relation(self, obj1, obj2, **hints):
"""
Relations between objects are allowed if both objects are
in the
master/slave
pool.
in the
leader/follower
pool.
"""
db_list = ('
master', 'slave1', 'slave
2')
db_list = ('
leader', 'follower1', 'follower
2')
if obj1._state.db in db_list and obj2._state.db in db_list:
return True
return None
...
...
@@ -347,17 +347,17 @@ Finally, in the settings file, we add the following (substituting
``path.to.`` with the actual python path to the module(s) where the
routers are defined)::
DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.
MasterSlave
Router']
DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.
LeaderFollower
Router']
The order in which routers are processed is significant. Routers will
be queried in the order the are listed in the
:setting:`DATABASE_ROUTERS` setting . In this example, the
``AuthRouter`` is processed before the ``
MasterSlave
Router``, and as a
``AuthRouter`` is processed before the ``
LeaderFollower
Router``, and as a
result, decisions concerning the models in ``auth`` are processed
before any other decision is made. If the :setting:`DATABASE_ROUTERS`
setting listed the two routers in the other order,
``
MasterSlave
Router.allow_migrate()`` would be processed first. The
catch-all nature of the
MasterSlave
Router implementation would mean
``
LeaderFollower
Router.allow_migrate()`` would be processed first. The
catch-all nature of the
LeaderFollower
Router implementation would mean
that all models would be available on all databases.
With this setup installed, lets run some Django code::
...
...
@@ -369,7 +369,7 @@ With this setup installed, lets run some Django code::
>>> # This save will also be directed to 'auth_db'
>>> fred.save()
>>> # These retrieval will be randomly allocated to a
slave
database
>>> # These retrieval will be randomly allocated to a
follower
database
>>> dna = Person.objects.get(name='Douglas Adams')
>>> # A new object has no database allocation when created
...
...
@@ -379,10 +379,10 @@ With this setup installed, lets run some Django code::
>>> # the same database as the author object
>>> mh.author = dna
>>> # This save will force the 'mh' instance onto the
mast
er database...
>>> # This save will force the 'mh' instance onto the
lead
er database...
>>> mh.save()
>>> # ... but if we re-retrieve the object, it will come back on a
slave
>>> # ... but if we re-retrieve the object, it will come back on a
follower
>>> mh = Book.objects.get(title='Mostly Harmless')
...
...
@@ -690,7 +690,7 @@ In addition, some objects are automatically created just after
database).
For common setups with multiple databases, it isn't useful to have these
objects in more than one database. Common setups include
master / slave
and
objects in more than one database. Common setups include
leader / follower
and
connecting to external databases. Therefore, it's recommended:
- either to run :djadmin:`migrate` only for the default database;
...
...
docs/topics/testing/advanced.txt
Dosyayı görüntüle @
73a57b06
...
...
@@ -64,16 +64,16 @@ The following is a simple unit test using the request factory::
Tests and multiple databases
============================
.. _topics-testing-
masterslave
:
.. _topics-testing-
leaderfollower
:
Testing
master/slave
configurations
Testing
leader/follower
configurations
-----------------------------------
If you're testing a multiple database configuration with
master/slave
If you're testing a multiple database configuration with
leader/follower
replication, this strategy of creating test databases poses a problem.
When the test databases are created, there won't be any replication,
and as a result, data created on the
mast
er won't be seen on the
slave
.
and as a result, data created on the
lead
er won't be seen on the
follower
.
To compensate for this, Django allows you to define that a database is
a *test mirror*. Consider the following (simplified) example database
...
...
@@ -83,34 +83,34 @@ configuration::
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'myproject',
'HOST': 'db
mast
er',
'HOST': 'db
lead
er',
# ... plus some other settings
},
'
slave
': {
'
follower
': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'myproject',
'HOST': 'db
slave
',
'HOST': 'db
follower
',
'TEST_MIRROR': 'default'
# ... plus some other settings
}
}
In this setup, we have two database servers: ``db
mast
er``, described
by the database alias ``default``, and ``db
slave
`` described by the
alias ``
slave``. As you might expect, ``dbslave
`` has been configured
by the database administrator as a read
slave of ``dbmast
er``, so in
normal activity, any write to ``default`` will appear on ``
slave
``.
In this setup, we have two database servers: ``db
lead
er``, described
by the database alias ``default``, and ``db
follower
`` described by the
alias ``
follower``. As you might expect, ``dbfollower
`` has been configured
by the database administrator as a read
follower of ``dblead
er``, so in
normal activity, any write to ``default`` will appear on ``
follower
``.
If Django created two independent test databases, this would break any
tests that expected replication to occur. However, the ``
slave
``
tests that expected replication to occur. However, the ``
follower
``
database has been configured as a test mirror (using the
:setting:`TEST_MIRROR` setting), indicating that under testing,
``
slave
`` should be treated as a mirror of ``default``.
``
follower
`` should be treated as a mirror of ``default``.
When the test environment is configured, a test version of ``
slave
``
will *not* be created. Instead the connection to ``
slave
``
When the test environment is configured, a test version of ``
follower
``
will *not* be created. Instead the connection to ``
follower
``
will be redirected to point at ``default``. As a result, writes to
``default`` will appear on ``
slave
`` -- but because they are actually
``default`` will appear on ``
follower
`` -- but because they are actually
the same database, not because there is data replication between the
two databases.
...
...
tests/migrations/test_operations.py
Dosyayı görüntüle @
73a57b06
...
...
@@ -765,7 +765,7 @@ class MultiDBOperationTests(MigrationTestBase):
multi_db
=
True
def
setUp
(
self
):
# Make the 'other' database appear to be a
slave
of the 'default'
# Make the 'other' database appear to be a
follower
of the 'default'
self
.
old_routers
=
router
.
routers
router
.
routers
=
[
MigrateNothingRouter
()]
...
...
tests/multiple_database/routers.py
Dosyayı görüntüle @
73a57b06
...
...
@@ -4,7 +4,7 @@ from django.db import DEFAULT_DB_ALIAS
class
TestRouter
(
object
):
# A test router. The behavior is vaguely
master/slave
, but the
# A test router. The behavior is vaguely
leader/follower
, but the
# databases aren't assumed to propagate changes.
def
db_for_read
(
self
,
model
,
instance
=
None
,
**
hints
):
if
instance
:
...
...
tests/multiple_database/tests.py
Dosyayı görüntüle @
73a57b06
...
...
@@ -854,7 +854,7 @@ class QueryTestCase(TestCase):
self
.
assertEqual
(
book
.
editor
.
_state
.
db
,
'other'
)
def
test_subquery
(
self
):
"""Make sure as_sql works with subqueries and
master/slave
."""
"""Make sure as_sql works with subqueries and
leader/follower
."""
sub
=
Person
.
objects
.
using
(
'other'
)
.
filter
(
name
=
'fff'
)
qs
=
Book
.
objects
.
filter
(
editor__in
=
sub
)
...
...
@@ -919,7 +919,7 @@ class RouterTestCase(TestCase):
multi_db
=
True
def
setUp
(
self
):
# Make the 'other' database appear to be a
slave
of the 'default'
# Make the 'other' database appear to be a
follower
of the 'default'
self
.
old_routers
=
router
.
routers
router
.
routers
=
[
TestRouter
()]
...
...
@@ -1071,7 +1071,7 @@ class RouterTestCase(TestCase):
try
:
dive
.
editor
=
marty
except
ValueError
:
self
.
fail
(
"Assignment across
master/slave
databases with a common source should be ok"
)
self
.
fail
(
"Assignment across
leader/follower
databases with a common source should be ok"
)
# Database assignments of original objects haven't changed...
self
.
assertEqual
(
marty
.
_state
.
db
,
'default'
)
...
...
@@ -1089,7 +1089,7 @@ class RouterTestCase(TestCase):
except
Book
.
DoesNotExist
:
self
.
fail
(
'Source database should have a copy of saved object'
)
# This isn't a real
master-slave
database, so restore the original from other
# This isn't a real
leader-follower
database, so restore the original from other
dive
=
Book
.
objects
.
using
(
'other'
)
.
get
(
title
=
'Dive into Python'
)
self
.
assertEqual
(
dive
.
_state
.
db
,
'other'
)
...
...
@@ -1097,7 +1097,7 @@ class RouterTestCase(TestCase):
try
:
marty
.
edited
=
[
pro
,
dive
]
except
ValueError
:
self
.
fail
(
"Assignment across
master/slave
databases with a common source should be ok"
)
self
.
fail
(
"Assignment across
leader/follower
databases with a common source should be ok"
)
# Assignment implies a save, so database assignments of original objects have changed...
self
.
assertEqual
(
marty
.
_state
.
db
,
'default'
)
...
...
@@ -1111,7 +1111,7 @@ class RouterTestCase(TestCase):
except
Book
.
DoesNotExist
:
self
.
fail
(
'Source database should have a copy of saved object'
)
# This isn't a real
master-slave
database, so restore the original from other
# This isn't a real
leader-follower
database, so restore the original from other
dive
=
Book
.
objects
.
using
(
'other'
)
.
get
(
title
=
'Dive into Python'
)
self
.
assertEqual
(
dive
.
_state
.
db
,
'other'
)
...
...
@@ -1119,7 +1119,7 @@ class RouterTestCase(TestCase):
try
:
marty
.
edited
.
add
(
dive
)
except
ValueError
:
self
.
fail
(
"Assignment across
master/slave
databases with a common source should be ok"
)
self
.
fail
(
"Assignment across
leader/follower
databases with a common source should be ok"
)
# Add implies a save, so database assignments of original objects have changed...
self
.
assertEqual
(
marty
.
_state
.
db
,
'default'
)
...
...
@@ -1133,7 +1133,7 @@ class RouterTestCase(TestCase):
except
Book
.
DoesNotExist
:
self
.
fail
(
'Source database should have a copy of saved object'
)
# This isn't a real
master-slave
database, so restore the original from other
# This isn't a real
leader-follower
database, so restore the original from other
dive
=
Book
.
objects
.
using
(
'other'
)
.
get
(
title
=
'Dive into Python'
)
# If you assign a FK object when the base object hasn't
...
...
@@ -1196,7 +1196,7 @@ class RouterTestCase(TestCase):
mark
=
Person
.
objects
.
using
(
'default'
)
.
create
(
pk
=
2
,
name
=
"Mark Pilgrim"
)
# Now save back onto the usual database.
# This simulates
master/slave
- the objects exist on both database,
# This simulates
leader/follower
- the objects exist on both database,
# but the _state.db is as it is for all other tests.
pro
.
save
(
using
=
'default'
)
marty
.
save
(
using
=
'default'
)
...
...
@@ -1213,7 +1213,7 @@ class RouterTestCase(TestCase):
try
:
marty
.
book_set
=
[
pro
,
dive
]
except
ValueError
:
self
.
fail
(
"Assignment across
master/slave
databases with a common source should be ok"
)
self
.
fail
(
"Assignment across
leader/follower
databases with a common source should be ok"
)
# Database assignments don't change
self
.
assertEqual
(
marty
.
_state
.
db
,
'default'
)
...
...
@@ -1232,7 +1232,7 @@ class RouterTestCase(TestCase):
try
:
marty
.
book_set
.
add
(
dive
)
except
ValueError
:
self
.
fail
(
"Assignment across
master/slave
databases with a common source should be ok"
)
self
.
fail
(
"Assignment across
leader/follower
databases with a common source should be ok"
)
# Database assignments don't change
self
.
assertEqual
(
marty
.
_state
.
db
,
'default'
)
...
...
@@ -1251,7 +1251,7 @@ class RouterTestCase(TestCase):
try
:
dive
.
authors
=
[
mark
,
marty
]
except
ValueError
:
self
.
fail
(
"Assignment across
master/slave
databases with a common source should be ok"
)
self
.
fail
(
"Assignment across
leader/follower
databases with a common source should be ok"
)
# Database assignments don't change
self
.
assertEqual
(
marty
.
_state
.
db
,
'default'
)
...
...
@@ -1273,7 +1273,7 @@ class RouterTestCase(TestCase):
try
:
dive
.
authors
.
add
(
marty
)
except
ValueError
:
self
.
fail
(
"Assignment across
master/slave
databases with a common source should be ok"
)
self
.
fail
(
"Assignment across
leader/follower
databases with a common source should be ok"
)
# Database assignments don't change
self
.
assertEqual
(
marty
.
_state
.
db
,
'default'
)
...
...
@@ -1311,7 +1311,7 @@ class RouterTestCase(TestCase):
try
:
bob
.
userprofile
=
alice_profile
except
ValueError
:
self
.
fail
(
"Assignment across
master/slave
databases with a common source should be ok"
)
self
.
fail
(
"Assignment across
leader/follower
databases with a common source should be ok"
)
# Database assignments of original objects haven't changed...
self
.
assertEqual
(
alice
.
_state
.
db
,
'default'
)
...
...
@@ -1342,7 +1342,7 @@ class RouterTestCase(TestCase):
try
:
review1
.
content_object
=
dive
except
ValueError
:
self
.
fail
(
"Assignment across
master/slave
databases with a common source should be ok"
)
self
.
fail
(
"Assignment across
leader/follower
databases with a common source should be ok"
)
# Database assignments of original objects haven't changed...
self
.
assertEqual
(
pro
.
_state
.
db
,
'default'
)
...
...
@@ -1361,7 +1361,7 @@ class RouterTestCase(TestCase):
except
Book
.
DoesNotExist
:
self
.
fail
(
'Source database should have a copy of saved object'
)
# This isn't a real
master-slave
database, so restore the original from other
# This isn't a real
leader-follower
database, so restore the original from other
dive
=
Book
.
objects
.
using
(
'other'
)
.
get
(
title
=
'Dive into Python'
)
self
.
assertEqual
(
dive
.
_state
.
db
,
'other'
)
...
...
@@ -1369,7 +1369,7 @@ class RouterTestCase(TestCase):
try
:
dive
.
reviews
.
add
(
review1
)
except
ValueError
:
self
.
fail
(
"Assignment across
master/slave
databases with a common source should be ok"
)
self
.
fail
(
"Assignment across
leader/follower
databases with a common source should be ok"
)
# Database assignments of original objects haven't changed...
self
.
assertEqual
(
pro
.
_state
.
db
,
'default'
)
...
...
@@ -1444,7 +1444,7 @@ class RouterTestCase(TestCase):
self
.
assertEqual
(
pro
.
reviews
.
db_manager
(
'default'
)
.
all
()
.
db
,
'default'
)
def
test_subquery
(
self
):
"""Make sure as_sql works with subqueries and
master/slave
."""
"""Make sure as_sql works with subqueries and
leader/follower
."""
# Create a book and author on the other database
mark
=
Person
.
objects
.
using
(
'other'
)
.
create
(
name
=
"Mark Pilgrim"
)
...
...
@@ -1482,7 +1482,7 @@ class AuthTestCase(TestCase):
multi_db
=
True
def
setUp
(
self
):
# Make the 'other' database appear to be a
slave
of the 'default'
# Make the 'other' database appear to be a
follower
of the 'default'
self
.
old_routers
=
router
.
routers
router
.
routers
=
[
AuthRouter
()]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment