1. 讀寫分離
- 192.168.1.2 default 主資料庫負責寫入
- 192.168.1.3 slave 從資料庫負責讀取
2. 生成資料庫表
python manage.py makemigrations
分別遷移到主從資料庫
python manage.py migrate --database=default
python manage.py migrate --database=slave
多個app分表:分app運算元據庫 假設app01對應資料庫default,app02對應資料庫slave
python manage.py makemigrations
python manage.py migrate app01 --database=default
python manage.py migrate app02 --database=slave
3. 開發時手動選擇使用資料庫
models.UserInfo.objects.using("default").create(title="admin")
models.UserInfo.objects.using("slave").all()
4. 多資料庫,多app操作配置
settings.py中增加資料庫配置
DATABASE_ROUTERS = ['KPIBackendSys.database_router.DatabaseAppsRouter'] # 讀寫檔案路徑
DATABASE_APPS_MAPPING = {
'app01': 'default',
'app02': 'slave',
}
DATABASES = {
# 預設AI資料庫
'default': {
'ENGINE': 'mssql', # 要連線的 資料庫型別
# 'ENGINE': 'sql_server.pyodbc', # 要連線的 資料庫型別
'NAME': db1, # 要連線的 資料庫名
'HOST': host, # 要連線的遠端資料庫的 ip地址
'PORT': port, # 資料庫連線埠,mysql預設3306
'USER': user, # 資料庫已有使用者名稱
'PASSWORD': pwd, # 資料庫已有使用者密碼
'OPTIONS': {
'driver': 'ODBC Driver 17 for SQL Server',
'MARS_Connection': True,
},
},
'slave': {
'ENGINE': 'mssql',
# 'ENGINE': 'sql_server.pyodbc', # 要連線的 資料庫型別
'NAME': db2,
'HOST': host, # 要連線的遠端資料庫的 ip地址
'PORT': port, # 資料庫連線埠,mysql預設3306
'USER': user, # 資料庫已有使用者名稱
'PASSWORD': pwd, # 資料庫已有使用者密碼
'OPTIONS': {
'driver': 'ODBC Driver 17 for SQL Server',
# 'MARS_Connection': True,
},
},
}
在settings.py同級目錄下增加database_router.py檔案
database_router.py
class DatabaseAppsRouter(object):
def db_for_read(self, model, **hints):
# 判斷模型類的元類中的app_label
if model._meta.app_label in DATABASE_MAPPING:
return DATABASE_MAPPING[model._meta.app_label]
return None
# 或直接判斷並返回資料庫
if model._meta.app_label == 'app01':
return default
if model._meta.app_label == 'app02':
return slave
def db_for_write(self, model, **hints):
"""
Point all write operations to the specific database.
"""
if model._meta.app_label in DATABASE_MAPPING:
return DATABASE_MAPPING[model._meta.app_label]
return None
# 或直接判斷並返回資料庫
if model._meta.app_label == 'app01':
return default
if model._meta.app_label == 'app02':
return slave
def allow_relation(self, obj1, obj2, **hints):
"""
Allow any relation between apps that use the same database.
"""
db_obj1 = DATABASE_MAPPING.get(obj1._meta.app_label)
db_obj2 = DATABASE_MAPPING.get(obj2._meta.app_label)
if db_obj1 and db_obj2:
if db_obj1 == db_obj2:
return True
else:
return False
return None
def allow_syncdb(self, db, model):
"""
Make sure that apps only appear in the related database.
"""
if db in DATABASE_MAPPING.values():
return DATABASE_MAPPING.get(model._meta.app_label) == db
elif model._meta.app_label in DATABASE_MAPPING:
return False
return None
def allow_migrate(self, db, app_label, model=None, **hints):
"""
Make sure the auth app only appears in the 'auth_db' database.
app_label, 表示使用的資料庫別名
"""
if db in DATABASE_MAPPING.values():
# 允許遷移到auth_db
return DATABASE_MAPPING.get(app_label) == db
elif app_label in DATABASE_MAPPING:
return False
# 不允許遷移
return None
5. 同一個app下的模型儲存在不同的資料庫
使用database_router.py中的allow_migrate方法, 讀寫操作同樣需要指定資料庫
class DatabaseAppsRouter(object):
def db_for_read(self, model, **hints):
# 判斷模型類的元類中的app_label
# 或直接判斷並返回資料庫
if model._meta.model_name in [model1, model2]:
return default
if model._meta.model_name in [model3, model3]:
return slave
def db_for_write(self, model, **hints):
# 或直接判斷並返回資料庫
if model._meta.model_name in [model1, model2]:
return default
if model._meta.model_name in [model3, model3]:
return slave
def allow_migrate(self, db, app_label, model=None, **hints):
if db == 'default':
if model_name in ['model1', 'model2']:
return True
return False
if db == 'slave':
if model_name in ['model3', 'model4']:
return True
return False