本篇文章將從數(shù)據(jù)庫遷移的原理出發(fā),詳細(xì)談一談在進(jìn)行數(shù)據(jù)庫遷移過程中的問題。
django框架就是一款強(qiáng)大的ORM框架,可以不需要寫sql語句就能進(jìn)行應(yīng)用開發(fā)。 ————官方說明文檔
一、
首先,簡短說一下數(shù)據(jù)庫遷移。說白了,其實(shí)就是將數(shù)據(jù)庫中的數(shù)據(jù)導(dǎo)出為sql語句來進(jìn)行sql操作。而對于django而言,強(qiáng)大之處就在于在通過遷移命令執(zhí)行數(shù)據(jù)庫遷移后,生成遷移sql語句腳本進(jìn)行相應(yīng)的數(shù)據(jù)庫操作。
在數(shù)據(jù)庫遷移之前,我們首先要生成遷移文件,命令耳熟能詳
python manage.py makemigrations
或者單獨(dú)對某一模塊進(jìn)行遷移操作
python manage.py makemigrations [模塊名]
這樣就生成了遷移文件,在相對應(yīng)的項(xiàng)目應(yīng)用中可以看到migrations文件夾下,生成一個(gè)新的以數(shù)字打頭的遷移文件。
而下一步就是執(zhí)行遷移操作了
python manage.py migrate
或者單獨(dú)遷移某一模塊
python manage.py migrate [模塊名]
遷移過之后,我們會(huì)發(fā)現(xiàn)在數(shù)據(jù)庫中多了遷移模型的數(shù)據(jù)表,查看相應(yīng)表也可以看到我們所建立的字段和類型。
但也多了幾張表,其中一張便是django_migrations,這張表即是記錄我們在每次執(zhí)行遷移操作時(shí)記錄的遷移文件的數(shù)據(jù)表。具體記錄的是模塊和與其對應(yīng)的遷移文件名。
二、
在我們協(xié)同開發(fā)過程中,遇到模型復(fù)用和更新迭代是最常見的事情,有時(shí)候我們會(huì)多次數(shù)據(jù)庫遷移來對舊表進(jìn)行修改。但隨著迭代版本的增加太多的遷移文件有時(shí)卻讓自己很煩,在版本控制時(shí)也會(huì)產(chǎn)生一些沖突和意想不到的bug。那么有時(shí)候就需要重新遷移文件,所以在刪除遷移文件migrations的同時(shí)還要清楚django_migrations表里的記錄。來再次重新遷移。
那么通過這一點(diǎn)規(guī)律來做一點(diǎn)小事情。
有時(shí)候,在版本控制的時(shí)候,每個(gè)人的操作習(xí)慣不太相同,有些開發(fā)者喜歡不提交遷移文件,而在服務(wù)器拉下代碼后進(jìn)行遷移操作。但當(dāng)項(xiàng)目上線之前跑量的過程中卻清除了數(shù)據(jù)庫中的數(shù)據(jù),再次提交migrate操作時(shí)就會(huì)出現(xiàn)遷移數(shù)據(jù)表已經(jīng)存在的錯(cuò)誤信息。(當(dāng)然,這并不影響服務(wù)器的運(yùn)行,也不會(huì)有任何異常,只是一直會(huì)有個(gè)報(bào)錯(cuò)而已罷了),對于我這樣的強(qiáng)迫癥是不能忍的,干掉錯(cuò)誤信息!一張兩張表可能我們會(huì)選擇刪除表之后重新遷移,但是如果模型過多刪除表的操作也相應(yīng)增多(況且,有一些表的數(shù)據(jù)我還不想全部刪除)。

那么,其實(shí)在清空表數(shù)據(jù)的同時(shí)備份django_migrations為sql文件是非常有必要的了。
三、
究竟該不該提交migrations?
官方文檔對于這個(gè)問題是這么解釋的
You should think of migrations as a version control system for your database schema. makemigrations is responsible for packaging up your model changes into individual migration files - analogous to commits - and migrate is responsible for applying those to your database.
The migration files for each app live in a “migrations” directory inside of that app, and are designed to be committed to, and distributed as part of, its codebase. You should be making them once on your development machine and then running the same migrations on your colleagues’ machines, your staging machines, and eventually your production machines.
中文翻譯
你可以想象 migrations 相當(dāng)一個(gè)你的數(shù)據(jù)庫的一個(gè)版本控制系統(tǒng)。makemigrations 命令負(fù)責(zé)保存你的模型變化到一個(gè)遷移文件 - 和 commits 很類似 - 同時(shí) migrate負(fù)責(zé)將改變提交到數(shù)據(jù)庫。
每個(gè) app 的遷移文件會(huì)保存到每個(gè)相應(yīng) app 的“migrations”文件夾里面,并且準(zhǔn)備如何去執(zhí)行它, 作為一個(gè)分布式代碼庫。 每當(dāng)在你的開發(fā)機(jī)器或是你同事的機(jī)器并且最終在你的生產(chǎn)機(jī)器上運(yùn)行同樣的遷移,你應(yīng)當(dāng)再創(chuàng)建這些文件。
其實(shí)無非是集中情況而已罷了
情況一: 開發(fā)環(huán)境和生產(chǎn)環(huán)境使用同一數(shù)據(jù)庫,
那么完全不用考慮這個(gè)問題,只要對django_migrations表進(jìn)行備份,不要誤刪就好了。在提交代碼時(shí)提交遷移文件,在服務(wù)器上也不用執(zhí)行相應(yīng)的遷移操作了。
情況二: 開發(fā)環(huán)境和生產(chǎn)環(huán)境使用不同數(shù)據(jù)庫,
那么這個(gè)問題其實(shí)也很好解決,提交遷移文件之后直接在服務(wù)器進(jìn)行遷移操作?;蛘卟惶峤辉诜?wù)器上自主生成遷移文件,再進(jìn)行遷移操作。那么在隨著版本迭代的過程中,開發(fā)環(huán)境的遷移文件也許會(huì)比生產(chǎn)環(huán)境的遷移文件多得多,那么就產(chǎn)生了也許在不同開發(fā)者的開發(fā)設(shè)備中版本不統(tǒng)一問題。再加上每人操作習(xí)慣不同,不提交遷移文件就會(huì)產(chǎn)生在服務(wù)器端重新遷移,對于日后的版本控制相當(dāng)不友好。
所以,其實(shí)對于遷移文件也是應(yīng)該直接提交至遠(yuǎn)程倉庫的。