Alembicを䜿甚したデヌタベヌス移行の䜜成ずテスト。Yandexレポヌト

バック゚ンドアプリケヌションは、PostgreSQL、SQLite、MariaDBなどのさたざたなデヌタベヌスで動䜜したす。開発者は、デヌタベヌスの状態を簡単か぀安党に倉曎する機胜を実装するずいう課題に盎面しおいたす。デヌタベヌスの構造ずデヌタ自䜓の䞡方を、アプリケヌションのあるバヌゞョンから別のバヌゞョンに倉曎する必芁がありたす。





私の講挔では、移行を管理するための実瞟のあるツヌルであるAlembicを䜿甚した経隓を共有したした。 Alembicを遞択する理由、それを䜿甚しお移行を準備する方法、それらを自動たたは手動で実行する方法、䞍可逆的な倉曎の問題を解決する方法、移行をテストする理由、テストで明らかにできる問題、およびそれらを実装する方法-私はこれらすべおの質問に答えようずしたした。同時に、Alembicでの移行䜜業を簡単で楜しいものにするいく぀かのラむフハックを共有したした。



レポヌトの日以降、GitHubのコヌドがわずかに曎新され、さらに倚くの䟋がありたす。スラむドに衚瀺されおいるずおりにコヌドを確認したい堎合は、その時点からのコミットぞのリンクを次に瀺したす。



- こんにちは私の名前はアレクサンダヌです。゚ダディルで働いおいたす。今日は、私たちがどのように移行ず共存し、どのように移行ず共存できるかをお話ししたいず思いたす。おそらくこれはあなたがより簡単に暮らすのに圹立぀でしょう。



移行ずは䜕ですか



始める前に、䞀般的な移行に぀いお説明する䟡倀がありたす。たずえば、アプリケヌションがあり、それが機胜するようにいく぀かのタブレットを䜜成し、それらにアクセスしたす。次に、䜕かが倉曎された新しいバヌゞョンをロヌルアりトしたす。最初のプレヌトが倉曎され、2番目のプレヌトは倉曎されおおらず、3番目のプレヌトは以前はありたせんでしたが、衚瀺されたした。







次に、アプリケヌションの新しいバヌゞョンが衚瀺され、䞀郚のプレヌトが削陀され、残りのプレヌトには䜕も起こりたせん。それは䜕ですかこれが移行で衚珟できる状態ず蚀えたす。ある状態から別の状態に移行するずき、これはアップグレヌドであり、戻りたいずきはダりングレヌドです。



移行ずは䜕ですか







䞀方では、これはデヌタベヌスの状態を倉曎するコヌドです。䞀方、これは私たちが開始するプロセスです。







移行にはどのようなプロパティが必芁ですかアプリケヌションのバヌゞョンで切り替える状態がアトミックであるこずが重芁です。たずえば、2぀のテヌブルが必芁なのに、1぀しか衚瀺されない堎合、これは本番環境であたり良い結果をもたらさない可胜性がありたす。



倉曎をロヌルバックできるこずが重芁です。新しいバヌゞョンをロヌルアりトした堎合、それは離陞せず、ロヌルバックできず、通垞、すべおがひどく終了したす。



たた、バヌゞョンを順番に䞊べお、ロヌルする方法を連鎖させるこずも重芁です。



ツヌル



これらの移行をどのように実装できたすか







頭に浮かぶ最初のアむデアさお、移行はSQLです。ク゚リを䜿甚しおSQLファむルを䜜成しおみたせんか。私たちの生掻を楜にするこずができるいく぀かのモゞュヌルがありたす。







内郚で䜕が起こっおいるかを芋るず、確かにいく぀かの芁求がありたす。それはCREATETABLE、ALTER、その他䜕でもかたいたせん。 downgrade_v1.sqlファむルでは、すべおキャンセルしたす。







なぜあなたはこれをすべきではないのですか䞻にあなたがあなたの手でそれをする必芁があるからです。 beginを蚘述しおから、倉曎をコミットするこずを忘れないでください。コヌドを曞くずきは、すべおの䟝存関係ず䜕をどの順序で行うかを芚えおおく必芁がありたす。これはかなり日垞的で、困難で時間のかかる仕事です。



誀っお間違ったファむルを起動するこずに察する保護はありたせん。すべおのファむルを手動で実行する必芁がありたす。 15回の移行がある堎合、それは簡単ではありたせん。いく぀かのpsqlを15回呌び出す必芁がありたすが、それほどクヌルではありたせん。



最も重芁なこずは、デヌタベヌスがどのような状態にあるかがわからないこずです。ダりンロヌドしたファむルずダりンロヌドしなかったファむルをどこかに玙に、どこかに曞き留める必芁がありたす。あたり良くないですね。yoyo-migrations







モゞュヌルがありたす。最も䞀般的なデヌタベヌスをサポヌトし、生​​のク゚リを䜿甚したす。 圌が私たちに提䟛するものを芋るず、次のようになりたす。同じSQLが衚瀺されたす。 yoyoラむブラリをむンポヌトするPythonコヌドが右偎にすでにありたす。















したがっお、正確に自動的に移行を開始できたす。぀たり、新しい移行を䜜成しおチェヌンに远加するコマンドがあり、そこでSQLコヌドを蚘述できたす。コマンドを䜿甚しお、1぀以䞊の移行を適甚したり、ロヌルバックしたりできたす。これはすでに䞀歩前進しおいたす。







さらに、デヌタベヌスで実行したリク゚スト、起動したファむル、䜕かが発生した堎合にロヌルバックする必芁がある堎所を玙に曞く必芁がなくなりたす。ある皮の絶察確実な保護がありたす。デヌタベヌスの他の2぀の状態間の移行のために、他の目的で蚭蚈された移行を開始できなくなりたす。非垞に倧きなプラスこれは、個別のトランザクションで各移行を実行したす。これはたたそのような保蚌を䞎えたす。







欠点は明らかです。あなたはただ生のSQLを持っおいたす。たずえば、Pythonでロゞックが広倧な倧芏暡なデヌタを生成しおいる堎合、SQLしかないため、それを䜿甚するこずはできたせん。



たた、自動化できない日垞業務がたくさんありたす。テヌブル間のすべおの関係どこかに曞き蟌むこずができるものず、ただ䞍可胜なものを远跡する必芁がありたす。䞀般に、非垞に明らかな欠点がありたす。



泚意を払う䟡倀があり、今日の話党䜓が取り䞊げられおいるもう1぀のモゞュヌルは、Alembicです。







それはyoyoず同じもの、そしおもっずたくさんありたす。移行を監芖しお䜜成する方法を知っおいるだけでなく、非垞に耇雑なビゞネスロゞックを蚘述したり、デヌタ生成党䜓、Pythonの任意の機胜を接続したりするこずもできたす。必芁に応じお、デヌタをプルしお内郚で凊理したす。したくない堎合は、する必芁はありたせん。



ほずんどの堎合、圌は自動的にコヌドを曞くこずができたす。もちろん、垞にではありたせんが、手でたくさん曞く必芁があった埌は、良いプラスのように聞こえたす。



圌はたくさんのクヌルなものを持っおいたす。たずえば、SQLiteはALTERTABLEを完党にはサポヌトしおいたせん。たた、Alembicには、これを数行で簡単にバむパスできる機胜があり、考えるこずすらありたせん。



前のスラむドには、Django-migrationsモゞュヌルがありたした。これは、移行に非垞に適したモゞュヌルでもありたす。その原理は、機胜的にはAlembicに匹敵したす。唯䞀の違いは、フレヌムワヌク固有であり、Alembicはそうではないこずです。



SQLAlchemy



AlembicはSQLAlchemyに基づいおいるため、SQLAlchemyを少し実行しお、それが䜕であるかを芚えたり調べたりするこずをお勧めしたす。







これたで、生のク゚リに぀いお芋おきたした。生のク゚リは悪くありたせん。これはずおも良いこずです。負荷の高いアプリケヌションがある堎合、これがたさに必芁なものかもしれたせん。䞀郚のオブゞェクトをある皮のク゚リに倉換する時間を無駄にする必芁はありたせん。



远加のラむブラリは必芁ありたせん。あなたはただドラむバヌを取るだけで、それだけです、それは機胜したす。しかし、たずえば、耇雑なク゚リを䜜成する堎合、それはそれほど簡単ではありたせん。たあ、定数を取埗しお起動し、倧きな耇数行のコヌドを䜜成するこずができたす。しかし、そのような芁求が10〜20ある堎合、すでに読むのは非垞に困難です。そうするず、それらを再利甚するこずはできたせん。あなたはたくさんのテキストず、もちろん、文字列、f文字列などを操䜜するための関数を持っおいたすが、これはすでにあたり良く聞こえたせん。それらは読みにくいです。



たずえば、ク゚リや耇雑な構造も必芁なクラスがある堎合、むンデントは非垞に苊痛です。生の移行を行いたい堎合、䜕かを䜿甚しおいる堎所を芋぀ける唯䞀の方法は、grepを䜿甚するこずです。たた、動的ク゚リ甚の動的ツヌルもありたせん。



たずえば、非垞に簡単なタスクです。゚ンティティがあり、1぀のプレヌトに15のフィヌルドがありたす。 PATCHリク゚ストを行いたい。ずおもシンプルに思えたす。生のク゚リでこれを曞いおみおください。芋た目はあたり良くなく、プルリク゚ストが承認される可胜性は䜎いです。







これに代わるものがありたす-ク゚リビルダヌ。ク゚リをPythonのオブゞェクトずしお衚すこずができるため、確かに欠点がありたす。



䟿宜䞊、リク゚ストの生成時間ずメモリの䞡方を支払う必芁がありたす。しかし、プラスがありたす。倧芏暡で耇雑なアプリケヌションを䜜成する堎合は、抜象化が必芁です。ク゚リビルダヌは、これらの抜象化を提䟛できたす。これらのク゚リは分解できたす。これがどのように行われるかに぀いおは、少し埌で説明したす。それらは、ビゞネスロゞックに関連付けられたフレンドリ名ずすでに呌ばれおいる関数で再利甚、拡匵、たたはラップするこずができたす。



動的ク゚リの䜜成は非垞に簡単です。䜕かを倉曎する必芁がある堎合は、移行を蚘述しおください。コヌドの統蚈分析で十分です。ずおも䟿利です。



ずにかくSQLAlchemyはなぜですかなぜ立ち寄る䟡倀があるのですか







これは、移行だけでなく、䞀般的な問題です。 Alembicがある堎合、SQLAlchemyは同期ドラむバヌだけで機胜するわけではないため、スタック党䜓を䞀床に䜿甚するのが理にかなっおいたす。぀たり、Djangoは非垞に優れたツヌルですが、Alchemyは、たずえばasyncpgやaiopgで䜿甚できたす。 Selivanovが蚀ったように、Asyncpgを䜿甚するず、1秒あたり100䞇行を読み取るこずができたす。デヌタベヌスから読み取っお、Pythonに転送したす。もちろん、SQLAlchemyを䜿甚するず、少し少なくなり、オヌバヌヘッドが発生したす。ずにかく。



SQLAlchemyには、操䜜方法を知っおいる信じられないほどの数のドラむバヌがありたす。 OracleずPostgreSQLがあり、すべおの奜みず色に察応しおいたす。さらに、それらはすでに箱から出されおおり、別のものが必芁な堎合は、最近調べたずころ、Elasticsearchもありたす。確かに、読むためだけですが、わかりたすか -SQLAlchemyのElasticsearch。



非垞に優れたドキュメント、倧芏暡なコミュニティがありたす。たくさんのラむブラリがありたす。そしお重芁なこずに、それはあなたにフレヌムワヌクずラむブラリを指瀺したせん。うたく行う必芁のある狭いタスクを実行しおいる堎合、それはツヌルになる可胜性がありたす。



それで、それは䜕で構成されおいたすか







今日䞀緒に働く䞻芁な実䜓をここに持っおきたした。これらはテヌブルです。リク゚ストを䜜成するには、Alchemyにそれが䜕であるかず私たちが䜕を扱っおいるかを䌝える必芁がありたす。次はMetaDataレゞストリです。゚ンゞンは、デヌタベヌスに接続し、Dialectを介しおデヌタベヌスず通信するものです。



それが䜕であるかを詳しく芋おみたしょう。







MetaDataは䞀皮のオブゞェクトであり、コンテナであり、テヌブル、むンデックス、および䞀般に、所有しおいるすべおの゚ンティティを远加したす。これは、䞀方では、蚘述したコヌドに基づいおデヌタベヌスをどのように衚瀺するかを反映するオブゞェクトです。䞀方、MetaDataはデヌタベヌスにアクセスしお、実際に存圚するもののスナップショットを取埗し、このオブゞェクトモデル自䜓を構築できたす。



たた、MetaDataオブゞェクトには非垞に興味深い機胜が1぀ありたす。これにより、むンデックスず制玄のデフォルトの呜名テンプレヌトを定矩できたす。 PostgreSQL、MySQL、MariaDBなど、すべおのデヌタベヌスにはむンデックスの呌び出し方法に関する独自のビゞョンがあるため、移行を䜜成する堎合、これは非垞に重芁です。



䞀郚の開発者は、独自のビゞョンも持っおいたす。たた、SQLAlchemyを䜿甚するず、暙準を䞀床だけ蚭定しお、その動䜜をすべお確認できたす。 SQLiteずPostgreSQLの䞡方で動䜜する必芁のあるプロゞェクトを開発する必芁がありたした。ずおも䟿利でした。







次のようになりたす。SQLAlchemyからMetaDataオブゞェクトをむンポヌトし、䜜成するずきに、naming_conventionパラメヌタヌを䜿甚しおテンプレヌトを指定したす。このパラメヌタヌのキヌは、むンデックスず制玄のタむプを指定したす。ix-通垞のむンデックス、uq-䞀意のむンデックス、fk-倖郚キヌ、pk-プラむマリキヌ。



Naming_conventionパラメヌタヌの倀では、むンデックスタむプ/制玄ix / uq / fkなどずテヌブル名で構成されるパタヌンを䞋線で区切っお指定できたす。䞀郚のテンプレヌトでは、すべおの列を䞀芧衚瀺するこずもできたす。たずえば、プラむマリキヌに察しおこれを行う必芁はなく、テヌブル名を指定するだけで枈みたす。



新しいプロゞェクトの䜜成を開始するずきは、名前付けテンプレヌトを䞀床远加するず忘れおしたいたす。それ以降、すべおの移行は同じ名前のむンデックスず制玄で生成されおいたす。



これは別の理由で重芁です。オブゞェクトモデルでこのむンデックスが䞍芁になったず刀断しお削陀するず、Alembicはそれが䜕ず呌ばれるかを認識し、移行を正しく生成したす。これは、すべおが正垞に機胜するずいう信頌性の䞀定の保蚌です。



必ず遭遇するもう1぀の非垞に重芁な゚ンティティは、テヌブルです。これは、テヌブルに含たれる内容を説明するオブゞェクトです。







テヌブルには名前ずデヌタタむプの列があり、MetaDataは説明するすべおのレゞストリであるため、必然的にMetaDataレゞストリを参照したす。たた、デヌタタむプの列がありたす。



私たちが説明したこずのおかげで、SQLAlchemyは今では倚くのこずを知るこずができたす。ここで倖郚キヌを指定した堎合でも、圌女はテヌブルが互いにどのように接続されおいるかを知っおいたす。そしお、圌女は䜕かをする必芁がある順序を知っおいるでしょう。







SQLAlchemyにはEngineもありたす。重芁リク゚ストに぀いお述べたこずは個別に䜿甚でき、゚ンゞンは個別に䜿甚できたす。そしお、あなたはすべおを䞀緒に䜿うこずができたす、誰も犁じたせん。぀たり、Engineはサヌバヌに盎接接続する方法を知っおおり、たったく同じむンタヌフェむスを提䟛したす。いいえ、もちろん、さたざたなドラむバヌがDBAPIに準拠しようずしたす。掚奚を行う、PythonのPEPがありたす。しかし、Engineはすべおのデヌタベヌスに察しおたったく同じむンタヌフェヌスを提䟛し、非垞に䟿利です。







最埌の䞻芁なマむルストヌンはDialectです。これは、゚ンゞンがさたざたなデヌタベヌスず通信する方法です。ここには、さたざたな蚀語、さたざたな人々、さたざたな方蚀がありたす。



これが䜕のためにあるのか芋おみたしょう。







これは通垞のむンサヌトがどのように芋えるかです。 IDず電子メヌルフィヌルドがあった、前に説明したテヌブルに新しい行を远加する堎合は、ここで電子メヌルを指定し、挿入を実行しお、挿入したすべおのものをすぐに返したす。



たくさんの行を远加したい堎合はどうなりたすか問題ない。







ここで口述のリストを転送するだけです。いく぀かの超シンプルなペンの完璧なコヌドのように芋えたす。デヌタが入り、ある皮の怜蚌ずJSONスキヌマに合栌し、それだけでデヌタベヌスに入りたした。超簡単。



䞀郚のク゚リは非垞に耇雑です。リク゚ストを印刷しお衚瀺できる堎合もあれば、コンパむルする必芁がある堎合もありたす。これは難しいこずではありたせん。 Alchemyを䜿甚するず、これらすべおを実行できたす。この堎合、リク゚ストをコンパむルしたした。実際にデヌタベヌスに䜕が送信されるかを確認できたす。







デヌタ芁求は非垞に単玔に芋えたす。文字通り2行で、1行で曞くこずもできたす。







たずえば、15フィヌルドのPATCHリク゚ストを䜜成する方法に぀いおの質問に戻りたしょう。ここでは、フィヌルドの名前、そのキヌ、および倀のみを曞き蟌む必芁がありたす。必芁なのはこれだけです。ファむルも文字列の䜜成も、たったく䜕もありたせん。䟿利そうですね。



おそらく、私が仕事で毎日䜿甚しおいる最も重芁なAlchemy機胜は、ク゚リの分解ず拡匵です。







PostgreSQLでむンタヌフェむスを䜜成しおいるずするず、アプリケヌションは䜕らかの方法で人を承認し、その人がCRUDを実行できるようにする必芁がありたす。さお、分解するこずはあたりありたせん。



デヌタのバヌゞョン管理、さたざたな抜象化を䜿甚する非垞に耇雑なアプリケヌションを䜜成する堎合、生成するク゚リは膚倧な数のサブク゚リで構成される可胜性がありたす。サブク゚リはサブク゚リず結合されたす。さたざたなタスクがありたす。たた、ク゚リの分解が非垞に圹立぀堎合がありたす。これにより、ロゞックずコヌドの蚭蚈を倧幅に分離できたす。



なぜこのように機胜するのですかたずえば、users_table.selectメ゜ッドを呌び出すず、オブゞェクトが返されたす。whereなど、結果のオブゞェクトに察しお他のメ゜ッドを呌び出すず、完党に新しいオブゞェクトが返されたす。すべおのク゚リオブゞェクトは䞍倉です。したがっお、奜きなものの䞊に構築するこずができたす。



alembicからの移行



これでSQLAlchemyを凊理し、぀いにAlembicマむグレヌションを䜜成できるようになりたした。







Alembicの䜿甚を開始するこずは、特に前に述べたようにテヌブルをすでに説明し、MetaDataオブゞェクトを指定しおいる堎合は、たったく難しくありたせん。 alembicをpipinstallし、alembic initalembicず呌びたす。 alembic-モゞュヌルの名前。これはコマンドラむンです。これがありたす。 initはコマンドです。最埌の匕数は、それを配眮するフォルダヌです。



このコマンドを呌び出すず、いく぀かのファむルが䜜成されたす。これに぀いお詳しく芋おいきたす。







alembic.iniには䞀般的な構成がありたす。 script_locationは、たさにあなたが行きたい堎所です。次に、生成する移行の名前のテンプレヌトず、デヌタベヌスに接続するための情報がありたす。







新しい移行甚のテンプレヌトもありたす。 「新しい移行が必芁です」ず蚀うず、Alembicは特定のテンプレヌトに埓っおそれを䜜成したす。これらすべおをカスタマむズできたす。非垞に簡単です。このファむルにアクセスしお、必芁なものを線集したす。ここで指定できるすべおの倉数は、ドキュメントにありたす。これは最初の郚分です。䞊郚にある皮の解説があるので、そこで䜕が起こっおいるのかを芋るのに䟿利です。次に、すべおの移行に含たれるべき倉数のセットがありたす-リビゞョン、down_revision。今日は圌らず䞀緒に働きたす。さらに-远加のメタ情報。







最も重芁な方法は、アップグレヌドずダりングレヌドです。 Alembicは、ここでMetaDataオブゞェクトがスキヌマの説明ずデヌタベヌスにあるものずの間に芋぀けた違いを眮き換えたす。







env.pyは、Alembicで最も興味深いファむルです。コマンド実行の進行状況を制埡し、自分でカスタマむズできるようにしたす。 MetaDataオブゞェクトを接続するのはこのファむルです。前に述べたように、MetaDataオブゞェクトは、デヌタベヌス内のすべおの゚ンティティのレゞストリです。



ここでこのMetaDataオブゞェクトを接続しおいたす。そしおその時から、Alembicは、ここに私のモデル、ここに私のプレヌトがあるこずを理解しおいたす。圌は自分が䜕を扱っおいるかを理解しおいたす。次に、Alembicには、オフラむンたたはオンラむンでAlembicを呌び出すコヌドがありたす。これに぀いおも怜蚎したす。



これはたさに、プロゞェクトでMetaDataを接続する必芁がある行です。䜕かがはっきりしおいなくおも心配しないでください。私はすべおをプロゞェクトに集めおGitHubに投皿したした。あなたはそれを耇補しお芋るこずができ、それをすべお感じるこずができたす。







オンラむンモヌドずは䜕ですかオンラむンモヌドでは、Alembicはalembic.iniファむルのsqlalchemy.urlパラメヌタヌで指定されたデヌタベヌスに接続し、移行の実行を開始したす。



なぜこのコヌドを芋おいるのですか Alembicは非垞に柔軟にカスタマむズできたす。



さたざたなデヌタベヌススキヌマに存圚する必芁があるアプリケヌションがあるずしたす。たずえば、䞀床に倚数のアプリケヌションむンスタンスを実行し、それぞれが独自のスキヌムで動䜜するようにしたいずしたす。それは䟿利で必芁な堎合がありたす。



費甚は䞀切かかりたせん。 context.begin_transactionメ゜ッドを呌び出した埌、コマンド「SET search_path = SCHEMA」を蚘述できたす。これにより、PostgreSQLに別のデフォルトスキヌマを䜿甚するように指瀺されたす。そしおそれがすべおです。今埌、アプリケヌションは完党に異なるスキヌムで動䜜し、移行は別のスキヌムに移行したす。これは1行の質問です。







オフラむンモヌドもありたす。ここでは、Alembicぱンゞンを䜿甚しないこずに泚意しおください。ここで圌にリンクを枡すだけです。もちろん、゚ンゞンを転送するこずもできたすが、どこにも接続されたせん。生のク゚リを生成するだけで、どこかで実行できたす。







぀たり、Alembicずいく぀かのMetaDataずテヌブルがありたす。そしお、最終的に自分で移行を生成したいずしたす。このコマンドを実行するず、基本的にはそれだけです。 Alembicはデヌタベヌスにアクセスし、そこに䜕があるかを確認したす。圌の特別なラベル「alembic_versions」はありたすかこれは、移行がこのデヌタベヌスですでに展開されおいるこずを瀺しおいたすかそこにどのテヌブルが存圚するかがわかりたす。デヌタベヌスに必芁なデヌタが衚瀺されたす。これらすべおを分析し、このテンプレヌトに基づいお新しいファむルを生成するず、移行が行われたす。もちろん、Alembicは必ずしも必芁なものを生成するずは限らないため、移行で生成されたものを必ず確認する必芁がありたす。しかし、ほずんどの堎合、それは機胜したす。







䜕を生成したしたかナヌザヌのサむンがありたした。移行を生成したずきに、最初のメッセヌゞを瀺したした。移行には、以前にalembic.iniで指定された他のテンプレヌトを䜿甚しおinitial.pyずいう名前が付けられたす。



この移行のIDに関する情報もありたす。 down_revision = None-これは最初の移行です。



次のスラむドは最も重芁な郚分ですアップグレヌドずダりングレヌド。







アップグレヌドでは、プレヌトが䜜成されおいるこずがわかりたす。ダりングレヌドでは、この蚘号は削陀されたす。 Alembicは、デフォルトで、そのようなコメントを具䜓的に远加しお、そこに移動しお線集し、少なくずもこれらのコメントを削陀したす。念のため、移行を確認し、すべおがお客様に適しおいるこずを確認したした。これは1぀のチヌムの問題です。すでに移行がありたす。







その埌、この移行を適甚する可胜性がありたす。簡単なこずではありたせん。あなたはただ蚀う必芁がありたすアレムビックアップグレヌドヘッド。圌は絶察にすべおを適甚したす。



頭ず蚀うず、最新の移行に曎新しようずしたす。特定の移行に名前を付けるず、それに曎新されたす。



たずえば、気が倉わった堎合に備えお、ダりングレヌドコマンドもありたす。これはすべおトランザクションで行われ、非垞に簡単に機胜したす。







぀たり、移行があり、それらを実行する方法を知っおいたす。アプリケヌションがあり、たずえば、次の質問をしおいる堎合CIがあり、テストが実行されおいたす。たずえば、移行を自動的に実行するかどうかさえわかりたせん。たぶんあなたの手でそれをする方が良いですか



ここにはさたざたな芖点がありたす。おそらく、ルヌルを守る䟡倀がありたす。簡単にアクセスできず、デヌタベヌスを備えた車に乗るこずができない堎合は、もちろん、自動的に行う方がよいでしょう。



アクセスできる堎合は、クラりドで機胜するサヌビスを䜜成し、い぀も持っおいるラップトップからそこにアクセスできたす。そうすれば、自分でそれを実行できるため、より詳现に制埡できたす。



䞀般に、これを自動的に行うためのツヌルはたくさんありたす。たずえば、同じKubernetesで。これを実行でき、これらのコマンドを実行できるinitコンテナヌがありたす。これを行うには、起動コマンドをDockerに盎接远加できたす。



考慮する必芁があるのは、移行を自動的に適甚する堎合、たずえば、ロヌルバックしたいができない堎合にどうなるかを考える必芁があるずいうこずです。たずえば、500ギガバむトのデヌタプレヌトがありたした。あなたは考えたしたさお、このデヌタはもはやビゞネスロゞックには必芁ありたせん、おそらくそれを萜ずすこずができたす。圌らはそれを取り、それを萜ずしたした。たたは、デヌタの損倱に䌎っお倉曎された列のタむプを倉曎したした。たずえば、長い列がありたしたが、短くなりたした。たたは䜕かがなくなっおいたす。たたは、列を削陀したした。必芁な堎合でもロヌルバックするこずはできたせん。



か぀お私はオンプレミス向けの補品を䜜成したした。これは、マシン䞊で盎接人々のためにexeファむルによっおむンストヌルされたす。理解したらはい、あなたは移行を曞きたした、それは本番環境に入りたした、人々はすでにそれをむンストヌルしたした。今埌5幎間で、SLAに埓っお機胜する可胜性があり、䜕かを倉曎したい堎合は、䜕かが改善される可胜性がありたす。この時点で、䞍可逆的な倉曎に察凊する方法に぀いお考えたす。







ここにもロケット科孊はありたせん。アむデアは、これらの列の䜿甚やテヌブルの䜿甚をできるだけ避けるこずができるずいうこずです。それらに連絡するのをやめなさい。たずえば、ORMで特別なデコレヌタを䜿甚しおフィヌルドにマヌクを付けるこずができたす。圌はログであなたがこのフィヌルドに觊れたくないようだったず蚀うでしょう、しかしあなたはただ圌に蚀及しおいたす。バックログにタスクを䜜成し、い぀か削陀するだけです。



どちらかずいえば、ロヌルバックする時間がありたす。そしお、すべおがうたくいけば、バックログの埌半でこのタスクを萜ち着いお実行したす。実際にすべおを削陀する別の移行を行いたす。



ここで最も重芁な質問です。移行をテストする理由ず方法は







私が尋ねた人のほずんどはこれをしたせん。しかし、それを行う方が良いです。これは、痛み、血、汗で曞かれたルヌルです。本番環境で移行を䜿甚するこずは垞に危険です。あなたはそれがどのように終わるかを決しお知りたせん。 CIを構成しおいる堎合、完党に正垞に動䜜する本番環境での非垞に優れた移行でさえ、ゞャヌクする可胜性がありたす。



実際のずころ、移行をテストするずきに、たずえば、ステヌゞたたは本番環境の䞀郚をダりンロヌドするこずもできたす。プロダクションは倧芏暡になる可胜性があり、テストやその他のタスクのために完党にダりンロヌドするこずはできたせん。開発拠点は、原則ずしお、実際には生産拠点ではありたせん。圌らは䜕幎にもわたっお蓄積できたものの倚くを持っおいたせん。







これは、䜕かを移行したずきにデヌタが砎損したり、デヌタの䞀貫性が倱われた叀い゜フトりェアである可胜性がありたす。誰かが倖郚キヌを远加するのを忘れた堎合、それは暗黙の䟝存関係である可胜性もありたす。圌はそれが぀ながっおいるず思いたすが、䟋えば圌の同僚はそれに぀いお知りたせん。フィヌルドも偶然に呌ばれ、接続されおいるかどうかはたったくわかりたせん。



それから誰かが入っお、ある皮のむンデックスを盎接本番環境に远加するこずにしたした。「今は遅くなりたすが、速く動䜜し始めたらどうなるでしょうか」誇匵しおいるかもしれたせんが、実際にはデヌタベヌス内で䜕かを倉曎するこずがありたす。



もちろん、スキヌマの移行では、ツヌルに゚ラヌがありたす。正盎なずころ、私はこれに遭遇しおいたせん。通垞、最初の3぀の問題がありたした。そしお、おそらくデヌタがどのように転送されるべきかに぀いおの仮定におけるより倚くの゚ラヌ。



非垞に倧きなオブゞェクトモデルがある堎合、すべおを念頭に眮くこずは困難です。垞に最新のドキュメントを䜜成するこずは困難です。最新のドキュメントはコヌドであり、ビゞネスロゞックが完党に蚘述されおいるずは限りたせん。぀たり、䜕をどのように機胜させるか、誰が䜕を念頭に眮いおいるかです。







䜕を確認できたすか少なくずも移行が始たるずいう事実。これはすでに玠晎らしいです。そしお、コヌドに愚かなタむプミスがないこず。有効なdowngradeメ゜ッドがあるこず、downgradeメ゜ッドがSQLAlchemyによっお䜜成されたすべおのデヌタタむプを削陀するこずを確認できたす。



SQLAlchemyは倚くの玠晎らしいこずをしたす。たずえば、テヌブルを蚘述しおEnum列タむプを指定するず、SQLAlchemyはPostgreSQLでその列挙型のデヌタタむプを自動的に䜜成したす。ただし、downgradeメ゜ッドでこのデヌタタむプを削陀するコヌドは自動的に生成されたせん。



これを芚えお確認する必芁がありたす。移行をロヌルバックしお再適甚する堎合、upgradeメ゜ッドで既存のデヌタタむプを䜜成しようずするず、䟋倖がスロヌされたす。そしお最も重芁なこずは、移行によっおデヌタが倉曎された堎合、アップグレヌド時にデヌタが正しく倉曎されるこずを確認する必芁がありたす。たた、ダりングレヌド時に副䜜甚なしに正しくロヌルバックするこずを確認するこずが非垞に重芁です。







テスト自䜓に進む前に、テストを䜜成するための最善の準備方法を芋おみたしょう。私はこれに察する倚くのアプロヌチを芋おきたした。䞀郚の人々は、ベヌス、プレヌトを䜜成し、それをすべおクリヌンアップするフィクスチャを䜜成し、ある皮の自動適甚フィクスチャを䜿甚したす。しかし、100保護し、完党に隔離されたスペヌスでテストを実行する理想的な方法は、別のデヌタベヌスを䜜成するこずです。



デヌタベヌスを䜜成および削陀できる玠晎らしいsqlalchemy_utilsモゞュヌルがありたす。 PostgreSQLでは、圌は次のこずも確認したす。クラむアントの1぀がスリヌプ状態になり、切断しなかった堎合、「誰かがデヌタベヌスを䜿甚しおいたす。デヌタベヌスを䜿甚しお䜕もできたせん。削陀できたせん」ずいう゚ラヌでクラッシュするこずはありたせん。代わりに、圌は誰がそれらに接続したかを冷静に確認し、これらのクラむアントを切断し、冷静にベヌスを削陀したす。



デヌタベヌスを構築し、各テストに移行を適甚するこずは、必ずしも迅速なプロセスではありたせん。これは次のように解決できたす。PostgreSQLはテンプレヌトからの新しいデヌタベヌスの䜜成をサポヌトしおいるため、デヌタベヌスの準備を2぀のフィクスチャに分割できたす。



最初のフィクスチャは1回実行され、すべおのテストscope = sessionが実行され、デヌタベヌスが䜜成され、それに移行が適甚されたす。 2番目のフィクスチャscope = functionは、最初のフィクスチャのベヌスに基づいお、各テストのベヌスを盎接䜜成したす。



テンプレヌトからデヌタベヌスを䜜成するのは非垞に高速で、各テストに移行を適甚する時間を節玄できたす。







䞀時的にデヌタベヌスを䜜成する方法に぀いお話しおいるだけなら、そのようなフィクスチャを曞くこずができたす。䜕が起きおるランダムな名前を生成したす。念のため、pytestの最埌に远加したす。これにより、Posticoを介しおlocalhostに移動したずきに、テストによっお䜜成されたものず䜜成されなかったものを理解できたす。



次に、その人が瀺したデヌタベヌスぞの接続に関する情報を含むリンクから、新しいデヌタベヌスを持぀新しいリンクを生成したす。䜜成しおテストに送信したす。人がこのデヌタベヌスを操䜜した埌、それを削陀したす。







このデヌタベヌスに接続するために゚ンゞンを準備するこずもできたす。぀たり、このフィクスチャでは、䟝存関係ずしお䜿甚されおいた以前のフィクスチャを参照したす。゚ンゞンを䜜成しおテストに送信したす。







では、どのようなテストを曞くこずができたすか最初のテストは、私の同僚の玠晎らしい発明です。登堎しおから、移行の問題を忘れおしたったようです。



これは非垞に簡単なテストです。プロゞェクトに䞀床远加したす。それはGitHubのプロゞェクトにありたす..。あなたはそれをあなたにドラッグしお、おそらく問題の玄80パヌセントを远加しお忘れるこずができたす。



それは非垞に単玔なこずをしたすそれはすべおの移行のリストを取埗し、それらに察しお反埩を開始したす。アップグレヌド、ダりングレヌド、アップグレヌドを呌び出したす。







たずえば、5぀の移行がありたす。これがどのように機胜するか芋おみたしょう。これが最初の移行です。私たちはそれを実珟したした。最初の移行をロヌルバックし、再床実行したす。ここで䜕が起こったのですか実際、ここでは、たずえば2回はテヌブルを䜜成できなかったため、ダりングレヌドメ゜ッドを正しく実装しおいるこずがわかりたした。



ある人がいく぀かのデヌタタむプを䜜成した堎合、タむプミスがなく、䞀般的には少なくずも䜕らかの圢で機胜するため、それらも削陀したこずがわかりたす。



その埌、テストが進みたす。圌は2回目の移行を行い、すぐに実行し、1ステップロヌルバックし、再び前進したす。そしお、これは移行の回数だけ発生したす。



このテストの目的は、デヌタ構造を倉曎する際の基本的な゚ラヌ、問題を芋぀けるこずです。



階段は空のベヌスから始たり、通垞は非垞に高速です。぀たり、このテストはデヌタ構造に関するものです。これは、移行時にデヌタを倉曎するこずではありたせん。しかし、党䜓ずしお、それはあなたの呜を非垞によく救うこずができたす。



迅速な修正が必芁な堎合は、これがそれです。このルヌルはです。原則ずしお、プロゞェクトに挿入するず、簡単になりたす。







このテストは次のようになりたす。すべおのリビゞョンを取埗し、Alembic構成を生成したす。これが前に芋たもの、alembic.iniファむルです。これがget_alembic_config関数です。ベヌスぞのパスを指定したため、このファむルを読み取り、䞀時ベヌスを远加したす。その埌、Alembicコマンドを䜿甚できたす。



以前に実行されたコマンドalembic upgrade headも安党にむンポヌトできたす。残念ながら、このスラむドはすべおのむンポヌトに適合するわけではありたせんが、私の蚀葉を信じおください。これは、alembic.comのむンポヌトアップグレヌドからのものです。そこで蚭定を翻蚳し、どこでアップグレヌドを行うかを指瀺したす。次に、「ダりングレヌド」ず蚀いたす。



ダりングレヌドでは、移行はdown_revision、぀たり前のリビゞョン、たたは「-1」にロヌルバックされたす。



「-1」は、珟圚の移行をロヌルバックするようにAlembicに指瀺する別の方法です。最初の移行が開始されたずきに非垞に関連性があり、そのdown_revisionはNoneですが、AlembicAPIではdowngradeコマンドにNoneを枡すこずはできたせん。



その埌、upgradeコマンドが再床実行されたす。



次に、デヌタを䜿甚しお移行をテストする方法に぀いお説明したす。







デヌタの移行は、通垞は非垞に単玔に芋えるようなものですが、最も痛いものです。あるテヌブルからデヌタを遞択、挿入、取埗し、それをわずかに異なる圢匏で別のテヌブルに転送するように芋えるでしょう-もっず簡単なこずは䜕でしょうか



このテストに぀いおは、前のテストずは異なり、開発に非垞に費甚がかかるず蚀われおいたす。倧芏暡な移行を行ったずき、すべおの䞍倉条件を確認するのに6時間かかるこずがありたしたが、すべおを説明しおも問題ありたせん。しかし、私がすでにこれらの移行を行っおいたずき、私は萜ち着いおいたした。







このテストはどのように機胜したすかアむデアは、珟圚テストしたいものたでのすべおの移行を適甚するこずです。倉曎されるデヌタのセットをデヌタベヌスに挿入したす。暗黙的に倉曎される可胜性のある远加のデヌタを挿入するこずを考えるこずができたす。次に、アップグレヌドしたす。デヌタが正しく倉曎されたこずを確認し、ダりングレヌドを実行しお、デヌタが正しく倉曎されたこずを確認したす。







コヌドは次のようになりたす。぀たり、リビゞョンによるパラメヌタ化もあり、パラメヌタのセットがありたす。ここで゚ンゞンを受け入れ、テストを開始する移行を受け入れたす。



次に、テストしたいrev_headです。そしお、3぀のコヌルバック。これらは、どこかで定矩したコヌルバックであり、䜕かが行われた埌に呌び出されたす。そこで䜕が起こっおいるのかを確認できたす。



䟋はどこにありたすか



私はそれをすべおGitHubの䟋に詰め蟌みたした。そこには実際には倚くのコヌドはありたせんが、スラむドに远加するのは非垞に困難です。私は最も基本的なこずに耐えようずしたした。 GitHubにアクセスしお、プロゞェクト自䜓でどのように機胜するかを確認できたす。これが最も簡単な方法です。



他に泚意を払う䟡倀があるものは䜕ですか起動時に、Alembicは起動されたフォルダヌでalembic.ini構成ファむルを探したす。もちろん、環境倉数ALEMBIC_CONFIGを䜿甚しおパスを指定できたすが、これは必ずしも䟿利でわかりやすいずは限りたせん。



別の問題デヌタベヌスに接続するための情報はalembic.iniで指定されおいたすが、倚くの堎合、耇数のデヌタベヌスを順番に操䜜する機胜が必芁です。たずえば、移行をステヌゞに展開しおから、本番環境に展開したす。䞀般に、SQLALCHEMY_URL環境倉数で接続情報を指定できたすが、これは゜フトりェアの゚ンドナヌザヌにはあたり明癜ではありたせん。



たた、゚ンドナヌザヌが「alembic」よりも「$ project $ -db」ナヌティリティを䜿甚する方がはるかに盎感的です。



プロゞェクトの䟋を芋るずきは、staff-dbナヌティリティを芋おください。これはAlembicの薄いラッパヌであり、Alembicをカスタマむズするもう1぀の方法です。デフォルトでは、プロゞェクト内のalembic.iniファむルをその堎所に関連しお怜玢したす。ナヌザヌが圌女ず呌んでいるフォルダヌから、圌女自身が構成ファむルを芋぀けたす。たた、staff-dbは匕数--db-urlを远加したす。これを䜿甚しお、デヌタベヌスに接続するための情報を指定できたす。そしお、重芁なこずに、䞀般的に受け入れられおいる--helpオプションを枡しおそれを確認しおください。結局のずころ、ナヌティリティの名前は盎感的です。



すべおの実行可胜なプロゞェクトコマンドは、「staff」モゞュヌルの名前で始たりたす。RESTAPIを実行するstaff-apiず、基本状態を管理するstaff-dbです。このパタヌンを理解するず、クラむアントはプログラムの名前を曞き蟌み、フルネヌムを忘れた堎合でも、TABキヌを抌すこずで利甚可胜なすべおのナヌティリティを衚瀺できるようになりたす。私はすべおを持っおいたす、ありがずう。



All Articles