假设您在网站the-app
上有一个Django 1.11应用the-site
。
在the-site/settings.py
中,您有以下数据库:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'the-site_webapp',
'USER': 'tester',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '3306',
},
'remote-db1': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'remote-db1',
'USER': 'tester',
'PASSWORD': '',
'HOST': '<ip1>',
'PORT': '3306',
},
'remote-db2': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'remote-db2',
'USER': 'tester',
'PASSWORD': '',
'HOST': '<ip2>',
'PORT': '3306',
},
}
其中remote-db2
包含remote-db1
的受限子集,因此可以替代它。
还有以下路由器信息:
DATABASE_ROUTERS = [ 'the-app.routers.DefaultRouter', 'the-app.routers.the-appRouter',]
指向the-app/routers.py
:
class MasterRouter(object):
'''
https://stackoverflow.com/questions/13988432/how-to-use-db-router-in-django-1-4
'''
def __init__(self, app_label, db_name):
super(MasterRouter, self).__init__()
self.app_label = app_label
self.db_name = db_name
def db_for_read(self, model, **hints):
if model._meta.app_label == self.app_label:
return self.db_name
#return self.app_label
return None
def db_for_write(self, model, **hints):
if model._meta.app_label == self.app_label:
return self.db_name
return None
def allow_relation(self, obj1, obj2, **hints):
if obj1._meta.app_label == self.app_label or obj2._meta.app_label == self.app_label:
return True
return None
def allow_syncdb(self, db, model):
if db == 'default':
return model._meta.app_label == self.app_label
elif model._meta.app_label == self.app_label:
return False
return None
def allow_migrate(self, db, *args, **kwargs):
if db in ['remote-db1']:
return False
class DefaultRouter(MasterRouter):
def __init__(self):
super(DefaultRouter, self).__init__('default', 'default')
class the-appRouter(MasterRouter):
def __init__(self):
super(the-appRouter, self).__init__('the-app', 'remote-db1')
在the-app/views.py
中,您有:
def foo (request):
try:
curfile = ModelName.objects.get(**arg_dict)
return _fetch_info(request, curfile)
except (KeyError, ModelName.DoesNotExist) as e:
messages.add_message(request, messages.ERROR, 'Couldn\'t find sample in remote-db1; attempting to connect to remote-db2')
try:
curfile = ModelName.objects.using('remote-db2').get(**arg_dict)
return _fetch_info(request, curfile)
except (KeyError, ModelName.DoesNotExist) as e:
messages.add_message(request, messages.ERROR, 'Couldn\'t fetch sample data.')
return render(request, 'foo.html')
except (OperationalError,) as e:
messages.add_message(request, messages.ERROR, 'Couldn\'t connect to remote-db2.')
traceback.print_exc() # debugging
return render(request, 'invalid.html')
except (OperationalError) as e:
messages.add_message(request, messages.ERROR, 'Couldn\'t connect to remote-db1. Trying remote-db2.')
traceback.print_exc() # debugging
try:
curfile = ModelName.objects.using('remote-db2').get(**arg_dict)
return _fetch_info(request, curfile)
except (KeyError, SampleFile.DoesNotExist) as e:
messages.add_message(request, messages.ERROR, 'Couldn\'t fetch sample data.')
return render(request, 'view_info.html')
except (OperationalError,) as e:
messages.add_message(request, messages.ERROR, 'Couldn\'t connect to either remote-db1 nor to remote-db2.')
traceback.print_exc() # debugging
return render(request, 'invalid.html')
查看traceback
日志,似乎发生的事情是,尽管我告诉Django .using('remote-db2')
连接到remote-db2
,但它会再次尝试连接到remote-db1
。
在我的某个地方是否可以处理此OperationalError(代码2003)?它looks like(第205行)这可能是不可能的(ever),但必须有某种方式来优雅地处理这个,除了呈现错误页面说&#34;稍后再试#34;!
非常感谢你的阅读时间和任何帮助,你可以给我:)。
编辑:我不管理遗留数据库和新数据库,因此我无法在数据库端轻松实现任何类型的负载平衡或故障转移策略。我被引导到django-failover:github.com/brianjaystanley/django-failover(抱歉,由于n00b状态,在帖子中不能超过2个链接),但是我使用的是python 3.5并且必须更新包,如果它仍然适用于Django 1.11!此外,两个远程数据库的模式略有不同,尽管它们包含有关相同对象的信息,因此django-failover不适用。
相关帖子:
(我在发布此帖之前读过其他人,但问题与Django pointing to MySQL db at localhost的错误配置有关)