<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # Migration Style Guide > 原文:[https://docs.gitlab.com/ee/development/migration_style_guide.html](https://docs.gitlab.com/ee/development/migration_style_guide.html) * [Schema Changes](#schema-changes) * [What Requires Downtime?](#what-requires-downtime) * [Downtime Tagging](#downtime-tagging) * [Reversibility](#reversibility) * [Atomicity](#atomicity) * [Heavy operations in a single transaction](#heavy-operations-in-a-single-transaction) * [Retry mechanism when acquiring database locks](#retry-mechanism-when-acquiring-database-locks) * [Examples](#examples) * [When to use the helper method](#when-to-use-the-helper-method) * [How the helper method works](#how-the-helper-method-works) * [Multi-Threading](#multi-threading) * [Removing indexes](#removing-indexes) * [Adding indexes](#adding-indexes) * [Adding foreign-key constraints](#adding-foreign-key-constraints) * [`NOT NULL` constraints](#not-null-constraints) * [Adding Columns With Default Values](#adding-columns-with-default-values) * [Changing the column default](#changing-the-column-default) * [Updating an existing column](#updating-an-existing-column) * [Dropping a database table](#dropping-a-database-table) * [Integer column type](#integer-column-type) * [Strings and the Text data type](#strings-and-the-text-data-type) * [Timestamp column type](#timestamp-column-type) * [Storing JSON in database](#storing-json-in-database) * [Testing](#testing) * [Data migration](#data-migration) * [Renaming reserved paths](#renaming-reserved-paths) # Migration Style Guide[](#migration-style-guide "Permalink") 在為 GitLab 編寫遷移時,必須考慮到這些遷移將由成千上萬個各種規模的組織來運行,其中一些組織的數據庫中包含多年的數據. 此外,對于大多數組織來說,必須使服務器脫機以進行較小或較大的升級是一大負擔. 因此,重要的是要仔細編寫遷移文件,可以在線進行遷移,并遵守下面的樣式指南. 遷移**不準**要求 GitLab 設施采取離線,除非*絕對必要的* . 如果需要停機,則必須通過以下方式批準遷移: 1. 工程副總裁 2. 后端維護者 3. 數據庫維護者 可以在[https://about.gitlab.com/company/team/中](https://about.gitlab.com/company/team/)找到持有這些頭銜的人員的最新列表. When writing your migrations, also consider that databases might have stale data or inconsistencies and guard for that. Try to make as few assumptions as possible about the state of the database. 請不要依賴特定于 GitLab 的代碼,因為它可能會在將來的版本中更改. 如果需要,將 GitLab 代碼復制粘貼到遷移中以使其向前兼容. 對于 GitLab.com,請考慮到在[部署 Canary](https://about.gitlab.com/handbook/engineering/infrastructure/library/canary/#configuration-and-deployment)之前運行常規遷移(在`db/migrate` ),在完成生產部署后運行部署后的遷移( `db/post_migrate` ). ## Schema Changes[](#schema-changes "Permalink") Changes to the schema should be committed to `db/structure.sql`. This file is automatically generated by Rails, so you normally should not edit this file by hand. If your migration is adding a column to a table, that column will be added at the bottom. Please do not reorder columns manually for existing tables as this will cause confusing to other people using `db/structure.sql` generated by Rails. 當您的 GDK 中的本地數據庫與`master`數據庫中的模式不同時,可能很難將模式更改完全提交給 Git. 在這種情況下,您可以使用`scripts/regenerate-schema`腳本為要添加的遷移重新生成干凈的`db/structure.sql` . 該腳本將應用在`db/migrate`或`db/post_migrate`找到的所有遷移,因此,如果您不想將任何遷移提交到架構,請重命名或刪除它們. 如果您的分支不是以`master`為目標,則可以設置`TARGET`環境變量. ``` # Regenerate schema against `master` scripts/regenerate-schema # Regenerate schema against `12-9-stable-ee` TARGET=12-9-stable-ee scripts/regenerate-schema ``` ## What Requires Downtime?[](#what-requires-downtime "Permalink") 文檔["什么需要停機?"](what_requires_downtime.html) 指定各種數據庫操作,例如 * [dropping and renaming columns](what_requires_downtime.html#dropping-columns) * [changing column constraints and types](what_requires_downtime.html#changing-column-constraints) * [adding and dropping indexes, tables, and foreign keys](what_requires_downtime.html#adding-indexes) 以及他們是否需要停機,以及如何盡可能地進行停機. ## Downtime Tagging[](#downtime-tagging "Permalink") 每個遷移都必須指定是否需要停機,并且如果需要停機,還必須指定原因. 這是即使在遷移的 99%,不需要停機,因為這使得它更容易地發現, *確實*需要停機遷移所需. 要標記遷移,請在遷移類的主體中添加以下兩個常量: * `DOWNTIME` :一個布爾值,當設置為`true`指示遷移需要停機時間. * `DOWNTIME_REASON` :一個字符串,其中包含需要停機的遷移原因. 當`DOWNTIME`設置為`true`時, **必須**設置此常數. 例如: ``` class MyMigration < ActiveRecord::Migration[6.0] DOWNTIME = true DOWNTIME_REASON = 'This migration requires downtime because ...' def change ... end end ``` 如果遷移類中缺少`DOWNTIME`常量,則會出現錯誤(即 CI 將失敗). ## Reversibility[](#reversibility "Permalink") 您的遷移**必須是**可逆的. 這非常重要,因為在出??現漏洞或錯誤的情況下應該可以降級. 在遷移中,添加一條注釋,描述如何測試遷移的可逆性. 某些遷移無法撤消. 例如,某些數據遷移無法撤消,因為在遷移之前,我們丟失了有關數據庫狀態的信息. 您仍然應該創建一個帶注釋的`down`方法,解釋為什么不能撤消`up`方法執行的更改,以便即使撤消遷移期間執行的更改也可以撤消遷移本身: ``` def down # no-op # comment explaining why changes performed by `up` cannot be reversed. end ``` ## Atomicity[](#atomicity "Permalink") 默認情況下,遷移是單個事務. 即,在遷移開始時打開一個事務,并在處理完所有步驟后提交. 在單個事務中運行遷移可確保如果其中一個步驟失敗,則將不會執行任何步驟,從而使數據庫保持有效狀態. 因此,要么: * 將所有遷移都放在一個單事務遷移中. * 如有必要,將大多數操作放入一個遷移中,并為無法在單個事務中完成的步驟創建一個單獨的遷移. 例如,如果創建一個空表并需要為其建立索引,則建議使用常規的單事務遷移和默認的 rails schema 語句: [`add_index`](https://api.rubyonrails.org/v5.2/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_index) . 這是一個阻塞操作,但不會引起問題,因為該表尚未使用,因此它還沒有任何記錄. ## Heavy operations in a single transaction[](#heavy-operations-in-a-single-transaction "Permalink") 使用單事務遷移時,事務將在遷移期間保持數據庫連接,因此您必須確保遷移中的操作不會花費太多時間:通常,在遷移中執行的查詢需要在 GitLab.com 上舒適地放置`15s` . 如果您需要插入,更新或刪除大量數據,請執行以下操作: * 必須使用`disable_ddl_transaction!`禁用單個事務`disable_ddl_transaction!` . * 應該考慮在[后臺遷移中](background_migrations.html)這樣做. ## Retry mechanism when acquiring database locks[](#retry-mechanism-when-acquiring-database-locks "Permalink") 更改數據庫架構時,我們使用輔助方法來調用 DDL(數據定義語言)語句. 在某些情況下,這些 DDL 語句需要特定的數據庫鎖. Example: ``` def change remove_column :users, :full_name, :string end ``` 要執行此遷移,需要對`users`表進行排他鎖定. 當表被其他進程同時訪問和修改時,獲取鎖定可能需要一段時間. 鎖定請求正在隊列中等待,一旦進入隊列,它也可能阻止`users`表上的其他查詢. 有關 PostgresSQL 鎖的更多信息: [顯式鎖定](https://s0www0postgresql0org.icopy.site/docs/current/explicit-locking.html) 出于穩定性考慮,GitLab.com 設置了特定的[`statement_timeout`](../user/gitlab_com/index.html#postgresql) . 調用遷移時,任何數據庫查詢都將有固定的執行時間. 在最壞的情況下,請求將坐在鎖定隊列中,在配置的語句超時時間內阻止其他查詢,然后`canceling statement due to statement timeout`錯誤`canceling statement due to statement timeout`失敗. 此問題可能導致應用程序升級過程失敗,甚至導致應用程序穩定性問題,因為該表可能會在短時間內無法訪問. 為了提高數據庫遷移的可靠性和穩定性,GitLab 代碼庫提供了一種輔助方法,以使用不同的`lock_timeout`設置重試操作,并在兩次嘗試之間等待時間. 為了獲得必要的鎖定,進行了多次較小的嘗試,從而使數據庫可以處理其他語句. ### Examples[](#examples "Permalink") **刪除列:** ``` include Gitlab::Database::MigrationHelpers def up with_lock_retries do remove_column :users, :full_name end end def down with_lock_retries do add_column :users, :full_name, :string end end ``` **刪除外鍵:** ``` include Gitlab::Database::MigrationHelpers def up with_lock_retries do remove_foreign_key :issues, :projects end end def down with_lock_retries do add_foreign_key :issues, :projects end end ``` **更改列的默認值:** ``` include Gitlab::Database::MigrationHelpers def up with_lock_retries do change_column_default :merge_requests, :lock_version, from: nil, to: 0 end end def down with_lock_retries do change_column_default :merge_requests, :lock_version, from: 0, to: nil end end ``` **用外鍵創建一個新表:** 我們可以簡單地用`with_lock_retries`包裝`create_table`方法: ``` def up with_lock_retries do create_table :issues do |t| t.references :project, index: true, null: false, foreign_key: { on_delete: :cascade } t.string :title, limit: 255 end end end def down drop_table :issues end ``` **當我們有兩個外鍵時創建一個新表:** 為此,我們需要進行三個遷移: 1. 創建不帶外鍵(帶有索引)的表. 2. 將外鍵添加到第一個表. 3. 將外鍵添加到第二個表. 創建表: ``` def up create_table :imports do |t| t.bigint :project_id, null: false t.bigint :user_id, null: false t.string :jid, limit: 255 end add_index :imports, :project_id add_index :imports, :user_id end def down drop_table :imports end ``` 在`projects`添加外鍵: ``` include Gitlab::Database::MigrationHelpers def up with_lock_retries do add_foreign_key :imports, :projects, column: :project_id, on_delete: :cascade end end def down with_lock_retries do remove_foreign_key :imports, column: :project_id end end ``` 向`users`添加外鍵: ``` include Gitlab::Database::MigrationHelpers def up with_lock_retries do add_foreign_key :imports, :users, column: :user_id, on_delete: :cascade end end def down with_lock_retries do remove_foreign_key :imports, column: :user_id end end ``` **與`disable_ddl_transaction!`配合使用`disable_ddl_transaction!`** 通常, `with_lock_retries`幫助程序應與`disabled_ddl_transaction!` . 定制的 RuboCop 規則可確保只能將允許的方法放在鎖重試塊中. ``` disable_ddl_transaction! def up with_lock_retries do add_column :users, :name, :text end add_text_limit :users, :name, 255 # Includes constraint validation (full table scan) end ``` RuboCop 規則通常允許使用下面列出的標準 Rails 遷移方法. 此示例將導致 Rubocop 犯罪: ``` disabled_ddl_transaction! def up with_lock_retries do add_concurrent_index :users, :name end end ``` ### When to use the helper method[](#when-to-use-the-helper-method "Permalink") 通常使用標準的 Rails 遷移幫助器方法時,可以使用`with_lock_retries`幫助器方法. 如果在同一個表上執行多個遷移助手,則調用它們不是問題. 當數據庫遷移涉及高流量表之一時,建議使用`with_lock_retries`幫助程序方法: * `users` * `projects` * `namespaces` * `issues` * `merge_requests` * `ci_pipelines` * `ci_builds` * `notes` 更改示例: * `add_foreign_key` / `remove_foreign_key` * `add_column` / `remove_column` * `change_column_default` * `create_table` / `drop_table` **注意:** `with_lock_retries`方法**不能**在`change`方法中使用,必須手動定義`up`和`down`方法以使遷移可逆. ### How the helper method works[](#how-the-helper-method-works "Permalink") 1. 重復 50 次. 2. 對于每次迭代,設置一個預配置的`lock_timeout` . 3. 嘗試執行給定的塊. ( `remove_column` ). 4. 如果出現`LockWaitTimeout`錯誤,請為預配置的`sleep_time`睡眠,然后重試該塊. 5. 如果未引發錯誤,則當前迭代已成功執行該塊. 有關更多信息,請檢查[`Gitlab::Database::WithLockRetries`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/with_lock_retries.rb)類. `with_lock_retries`幫助器方法在[`Gitlab::Database::MigrationHelpers`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/database/migration_helpers.rb)模塊中實現. 在最壞的情況下,該方法: * 在 40 分鐘內最多執行 50 次該塊. * 大部分時間都花費在每次迭代后的預先配置的睡眠時段中. * 第 50 次重試之后,將像標準遷移調用一樣在沒有`lock_timeout`情況下執行該塊. * 如果無法獲取鎖,則遷移將失敗,并出現`statement timeout`錯誤. 如果訪問`users`表的事務運行時間很長(超過 40 分鐘),則遷移可能會失敗. ## Multi-Threading[](#multi-threading "Permalink") 有時,遷移可能需要使用多個 Ruby 線程來加快遷移速度. 為此,您的遷移需要包括模塊`Gitlab::Database::MultiThreadedMigration` : ``` class MyMigration < ActiveRecord::Migration[6.0] include Gitlab::Database::MigrationHelpers include Gitlab::Database::MultiThreadedMigration end ``` 然后可以使用`with_multiple_threads`方法在單獨的線程中執行工作. 例如: ``` class MyMigration < ActiveRecord::Migration[6.0] include Gitlab::Database::MigrationHelpers include Gitlab::Database::MultiThreadedMigration def up with_multiple_threads(4) do disable_statement_timeout # ... end end end ``` 在這里,對`disable_statement_timeout`的調用將使用`with_multiple_threads`塊本地的連接,而不是重新使用全局連接池. 這樣可以確保每個線程都有自己的連接對象,并且在嘗試獲取一個連接對象時不會超時. **注意:** PostgreSQL 具有允許的最大連接數. 此限制因安裝而異. 因此,建議您一次遷移不要使用超過 32 個線程. 通常,4-8 個線程應該綽綽有余. ## Removing indexes[](#removing-indexes "Permalink") 如果刪除索引時表不為空,請確保使用方法`remove_concurrent_index`而不是常規的`remove_index`方法. `remove_concurrent_index`方法同時刪除索引,因此不需要鎖定,也無需停機. 要使用此方法,必須通過調用方法`disable_ddl_transaction!`禁用單交易模式`disable_ddl_transaction!` 在您的遷移類的主體中,如下所示: ``` class MyMigration < ActiveRecord::Migration[6.0] include Gitlab::Database::MigrationHelpers disable_ddl_transaction! def up remove_concurrent_index :table_name, :column_name end end ``` 請注意,在刪除索引之前不必檢查索引是否存在. 對于較小的表(例如空表或少于`1,000`條記錄的表),建議在單事務遷移中使用`remove_index` ,并將其與不需要`disable_ddl_transaction!`其他操作結合使用`disable_ddl_transaction!` . ## Adding indexes[](#adding-indexes "Permalink") 在添加索引之前,請考慮該索引是否必要. 在某些情況下可能不需要索引,例如: * 該表很小(少于`1,000`條記錄),并且預計大小不會成倍增長. * 任何現有索引都會過濾掉足夠的行. * 添加索引后查詢時間的減少并不明顯. 另外,不需要寬索引來匹配查詢的所有過濾條件,我們只需要覆蓋足夠多的列即可使索引查找具有足夠小的選擇性. 請查看我們的[添加數據庫索引](adding_database_indexes.html)指南以獲取更多詳細信息. 將索引添加到非空表時,請確保使用方法`add_concurrent_index`而不是常規的`add_index`方法. 使用 PostgreSQL 時, `add_concurrent_index`方法自動創建并發索引,從而消除了停機時間. 要使用此方法,必須通過調用方法`disable_ddl_transaction!`禁用單交易模式`disable_ddl_transaction!` 在您的遷移類的主體中,如下所示: ``` class MyMigration < ActiveRecord::Migration[6.0] include Gitlab::Database::MigrationHelpers DOWNTIME = false disable_ddl_transaction! def up add_concurrent_index :table, :column end def down remove_concurrent_index :table, :column end end ``` 如果需要添加唯一索引,請記住,數據庫中可能存在現有重復項. 這意味著在添加唯一索引之前,應始終*首先*添加一個刪除所有重復項的遷移. 對于小型表(例如空表或少于`1,000`條記錄的表),建議在單事務遷移中使用`add_index` ,并將其與不需要`disable_ddl_transaction!`其他操作結合使用`disable_ddl_transaction!` . ## Adding foreign-key constraints[](#adding-foreign-key-constraints "Permalink") 向現有列或新列添加外鍵約束時,還請記住在該列上添加索引. 這是所有外鍵所**必需**的,例如,為了支持有效的級聯刪除:當刪除表中的許多行時,也需要刪除引用的記錄. 數據庫必須在引用的表中查找相應的記錄. 沒有索引,這將導致對表進行順序掃描,這可能需要很長時間. 這是一個示例,其中我們添加了一個帶有外鍵約束的新列. 請注意,它包括`index: true`為其創建索引. ``` class Migration < ActiveRecord::Migration[6.0] def change add_reference :model, :other_model, index: true, foreign_key: { on_delete: :cascade } end end ``` 當向非空表中的現有列添加外鍵約束時,我們必須使用`add_concurrent_foreign_key`和`add_concurrent_index`而不是`add_reference` . 對于空表(例如新表),建議在單事務遷移中使用`add_reference` ,并將其與不需要`disable_ddl_transaction!`其他操作結合使用`disable_ddl_transaction!` . 您可以閱讀有關將[外鍵約束](database/add_foreign_key_to_existing_column.html)添加[到現有列的更多信息](database/add_foreign_key_to_existing_column.html) . ## `NOT NULL` constraints[](#not-null-constraints "Permalink") [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/38358) in GitLab 13.0. 有關更多信息,請參見關于[`NOT NULL`約束](database/not_null_constraints.html)的樣式指南. ## Adding Columns With Default Values[](#adding-columns-with-default-values "Permalink") PostgreSQL 11 是自 GitLab 13.0 以來的最低版本,添加具有默認值的列變得更加容易,并且在所有情況下都應使用標準的`add_column`幫助器. 在 PostgreSQL 11 之前,添加帶有默認值的列是有問題的,因為這會導致全表重寫. 相應的幫助程序`add_column_with_default`已被棄用,并將在以后的版本中刪除. **注意:**如果%12.9 或更早版本需要向后端口添加具有默認值的列,則應使用`add_column_with_default`幫助器. 如果涉及[大表](https://gitlab.com/gitlab-org/gitlab/-/blob/master/rubocop/rubocop-migrations.yml#L3) ,則禁止向后移植到%12.9. ## Changing the column default[](#changing-the-column-default "Permalink") 可能有人認為,使用`change_column_default`更改默認列對于較大的表來說是一項昂貴且破壞性的操作,但實際上并非如此. 以以下遷移為例: ``` class DefaultRequestAccessGroups < ActiveRecord::Migration[5.2] DOWNTIME = false def change change_column_default(:namespaces, :request_access_enabled, from: false, to: true) end end ``` 上面的遷移更改了我們最大的表之一的默認列值: `namespaces` . 可以將其翻譯為: ``` ALTER TABLE namespaces ALTER COLUMN request_access_enabled DEFAULT false ``` 在這種情況下,默認值存在,我們只是更改了`request_access_enabled`列的元數據,這并不意味著重寫`namespaces`表中的所有現有記錄. 僅當使用默認值創建新列時,所有記錄才會被重寫. **注意:** PostgresSQL 11.0 引入[了](https://www.depesz.com/2018/04/04/waiting-for-postgresql-11-fast-alter-table-add-column-with-a-non-null-default/)更快的[ALTER TABLE ADD COLUMN(具有非空默認值](https://www.depesz.com/2018/04/04/waiting-for-postgresql-11-fast-alter-table-add-column-with-a-non-null-default/) ),從而消除了在添加具有默認值的新列時重寫表的需求. 由于上述原因,在單事務遷移中使用`change_column_default`是安全的,而不需要`disable_ddl_transaction!` . ## Updating an existing column[](#updating-an-existing-column "Permalink") 要將現有列更新為特定值,可以使用`update_column_in_batches` . 這會將更新分為批次,因此我們不會在單個語句中更新太多行. 這`some_column` `projects`表中的`foo`列更新為 10,其中`some_column`為`'hello'` : ``` update_column_in_batches(:projects, :foo, 10) do |table, query| query.where(table[:some_column].eq('hello')) end ``` 如果需要計算的更新,則可以將值包裝在`Arel.sql` ,因此 Arel 將其視為 SQL 文字. 這也是[Rails 6](https://gitlab.com/gitlab-org/gitlab/-/issues/28497)的必需棄用. 下面的示例與上面的示例相同,但是該值設置為`bar`和`baz`列的乘積: ``` update_value = Arel.sql('bar * baz') update_column_in_batches(:projects, :foo, update_value) do |table, query| query.where(table[:some_column].eq('hello')) end ``` 像`add_column_with_default`一樣,有一個 RuboCop cop 可以檢測大表上的用法. 在`update_column_in_batches`的情況下,可以在大表上運行,只要它僅更新表中行的一小部分,而在未在 GitLab.com 登臺環境上進行驗證的情況下不要忽略它-或事先請別人為您這樣做. ## Dropping a database table[](#dropping-a-database-table "Permalink") 刪除數據庫表并不常見,Rails 提供的`drop_table`方法通常被認為是安全的. 刪除表格之前,請考慮以下因素: 如果您的表在高流量表上具有外鍵(如`projects` ),則`DROP TABLE`語句可能會失敗,并出現**語句超時**錯誤. 確定哪些表是高流量可能很困難. 自我管理的實例可能會以不同的使用模式使用 GitLab 的不同功能,因此僅基于 GitLab.com 進行假設是不夠的. 表**沒有記錄** (功能從未使用過),也**沒有外鍵** : * 只需在遷移中使用`drop_table`方法即可. ``` def change drop_table :my_table end ``` Table **有記錄** but **沒有外鍵**: * 第一版:刪除與表相關的應用程序代碼,例如模型,控制器和服務. * 第二版:在遷移中使用`drop_table`方法. ``` def up drop_table :my_table end def down # create_table ... end ``` Table **有外鍵**: * 第一版:刪除與表相關的應用程序代碼,例如模型,控制器和服務. * 第二版:使用`with_lock_retries`幫助器方法刪除外鍵. 在另一個遷移文件中使用`drop_table` . **第二個版本的遷移:** 刪除`projects`表上的外鍵: ``` # first migration file def up with_lock_retries do remove_foreign_key :my_table, :projects end end def down with_lock_retries do add_foreign_key :my_table, :projects end end ``` 放下桌子: ``` # second migration file def up drop_table :my_table end def down # create_table ... end ``` ## Integer column type[](#integer-column-type "Permalink") 默認情況下,整數列最多可容納 4 個字節(32 位)的數字. 最大值為 2,147,483,647\. 創建一個以字節為單位保存文件大小的列時,請注意這一點. 如果以字節為單位跟蹤文件大小,這會將最大文件大小限制為剛好超過 2GB. 要允許整數列最多容納 8 個字節(64 位)的數字,請將限制明確設置為 8 個字節. 這將使該列最多`9,223,372,036,854,775,807`個值. Rails 遷移示例: ``` add_column(:projects, :foo, :integer, default: 10, limit: 8) ``` ## Strings and the Text data type[](#strings-and-the-text-data-type "Permalink") 在 GitLab 13.0 中[引入](https://gitlab.com/gitlab-org/gitlab/-/issues/30453) . 有關更多信息,請參見[文本數據類型](database/strings_and_the_text_data_type.html)樣式指南. ## Timestamp column type[](#timestamp-column-type "Permalink") 默認情況下,Rails 使用`timestamp`數據類型來存儲沒有時區信息的時間戳數據. 通過調用`add_timestamps`或`timestamps`方法來使用`timestamp`數據類型. 另外,Rails 將`:datetime`數據類型轉換為`timestamp`一. Example: ``` # timestamps create_table :users do |t| t.timestamps end # add_timestamps def up add_timestamps :users end # :datetime def up add_column :users, :last_sign_in, :datetime end ``` 代替使用這些方法,應該使用以下方法來存儲帶有時區的時間戳: * `add_timestamps_with_timezone` * `timestamps_with_timezone` * `datetime_with_timezone` 這樣可以確保所有時間戳都有指定的時區. 反過來,這意味著當系統的時區更改時,現有時間戳不會突然使用其他時區. 這也使得非常清楚,首先使用了哪個時區. ## Storing JSON in database[](#storing-json-in-database "Permalink") Rails 5 本機支持`JSONB` (二進制 JSON)列類型. 添加此列的示例遷移: ``` class AddOptionsToBuildMetadata < ActiveRecord::Migration[5.0] DOWNTIME = false def change add_column :ci_builds_metadata, :config_options, :jsonb end end ``` 您必須使用序列化器來提供翻譯層: ``` class BuildMetadata serialize :config_options, Serializers::JSON # rubocop:disable Cop/ActiveRecordSerialize end ``` 使用`JSONB`列時,請使用[JsonSchemaValidator](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/validators/json_schema_validator.rb)來控制隨時間推移插入的數據. ``` class BuildMetadata validates :config_options, json_schema: { filename: 'build_metadata_config_option' } end ``` ## Testing[](#testing "Permalink") 請參閱" [測試 Rails 遷移](testing_guide/testing_migrations_guide.html)樣式"指南. ## Data migration[](#data-migration "Permalink") 請比一般 ActiveRecord 語法更喜歡 Arel 和普通 SQL. 如果使用普通 SQL,則需要使用`quote_string` helper 手動引用所有輸入. Arel 的示例: ``` users = Arel::Table.new(:users) users.group(users[:user_id]).having(users[:id].count.gt(5)) #update other tables with these results ``` 帶有普通 SQL 和`quote_string`幫助器的示例: ``` select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(id) > 1").each do |tag| tag_name = quote_string(tag["name"]) duplicate_ids = select_all("SELECT id FROM tags WHERE name = '#{tag_name}'").map{|tag| tag["id"]} origin_tag_id = duplicate_ids.first duplicate_ids.delete origin_tag_id execute("UPDATE taggings SET tag_id = #{origin_tag_id} WHERE tag_id IN(#{duplicate_ids.join(",")})") execute("DELETE FROM tags WHERE id IN(#{duplicate_ids.join(",")})") end ``` 如果需要更復雜的邏輯,則可以定義和使用遷移本地模型. 例如: ``` class MyMigration < ActiveRecord::Migration[6.0] class Project < ActiveRecord::Base self.table_name = 'projects' end def up # Reset the column information of all the models that update the database # to ensure the Active Record's knowledge of the table structure is current Project.reset_column_information # ... ... end end ``` 這樣做時,請確保顯式設置模型的表名,這樣它就不會派生自類名或名稱空間. 最后,對于所有更新數據庫的本地模型,請確保在遷移的`up`方法中運行`reset_column_information` . 這樣做的原因是所有遷移類都在開始時加載( `db:migrate`啟動時),因此,如果另一個遷移更新了該模式,它們將與它們映射的表模式不同步. 這將導致在嘗試插入基礎表或對其進行更新時數據遷移失敗,因為`ActiveRecord`將新列報告為`unknown attribute` . ### Renaming reserved paths[](#renaming-reserved-paths "Permalink") 引入新的項目路線時,它可能與任何現有記錄沖突. 這些記錄的路徑應重命名,并且相關數據應在磁盤上移動. 由于我們已經必須做幾次,因此現在有一些幫助程序可以幫助您. 要使用此功能,您可以在遷移中包括`Gitlab::Database::RenameReservedPathsMigration::V1` . 這將提供 3 種方法,您可以通過一種或多種需要拒絕的路徑. **`rename_root_paths`** :這將使用給定名稱重命名所有沒有`parent_id`名稱*空間*的路徑. **`rename_child_paths`** :這將使用給定名稱重命名所有具有`parent_id`名稱*空間*的路徑. **`rename_wildcard_paths`** :這將重命名所有*項目*的路徑以及所有具有`project_id` *命名空間* . 這些行的`path`列將重命名為其先前的值,后跟一個整數. 例如: `users`將變成`users0`
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看