---
title: "停止時間なしのアップグレード"
description: "セルフホスト版 Quire を停止時間なしでアップグレードします。"
image: "https://docs.quirelms.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.quirelms.com/ja/llms.txt
> Use this file to discover all available pages before exploring further.

# 停止時間なしのアップグレード

<span id="upgrading-without-downtime"></span>

手順は `docs/architecture/23-ops.md` のセクション 7 と `docs/architecture/07-data.md` のセクション 4.1 にあります。以下が作業手順です。

## 安全性を保証する仕組み <!--quire:the-guarantee-that-makes-it-safe-->

**リリース R はスキーマ R と R-1 の両方で正しく動作します。** スキーマ変更は拡張、移行、縮約の 3 段階に分けます。

1. **拡張**: 新しい列、テーブル、インデックスを追加します。古いコードは無視します。
2. **移行**: 少なくとも 1 リリースの間、新しいコードは新旧両方の形式を書き、新形式を読み取ります。再開可能なジョブで古い行を埋めます。
3. **縮約**: 旧形式を後続リリースで単独で削除します。

そのためローリングアップグレード中も、旧プロセスと新プロセスが同じデータベースを使えます。ダウンマイグレーションはありません。1 時間前に列を削除するマイグレーションを戻しても、その 1 時間に書き込まれた行は復元できないためです。

`schema-compat` CI ジョブは、旧リリースのテストを新しいスキーマに対して実行し、すべてのリリースでこの保証を確認します。

## 開始前 <!--quire:before-you-start-->

1. リリースノートを読みます。メンテナンス時間が必要なリリースでは所要時間が記載されます。1 リリースにつき最大 1 回です。
2. 復元ドリルを実行するか、このリリースで成功済みであることを確認します ([backup-restore.md](/ja/ops/backup-restore/))。ドリルが失敗した場合はアップグレードできません。
3. ベースバックアップを作成します。 `docker compose -f docker/compose.yaml --profile backup run --rm backup`

## Docker Compose、単一ホスト <!--quire:docker-compose-one-host-->

```sh
export QUIRE_RELEASE=2026.10.0            # or set it in docker/.env
docker compose -f docker/compose.yaml pull   # or build
docker compose -f docker/compose.yaml run --rm migrate
docker compose -f docker/compose.yaml up -d --no-deps web content collab
docker compose -f docker/compose.yaml up -d --no-deps worker scheduler
```

実行順序には理由があります。

1. 旧リリースがトラフィックを処理している間に、**先にマイグレーション** を実行します。拡張マイグレーションは旧コードから見えません。
2. **次に Web 層** を更新します。SIGTERM を受け取ると各 Web プロセスは `/readyz` を `draining` にし、処理中のリクエストを 30 秒以内に完了し、再接続を促すヒントとともにストリームを閉じて終了します。`stop_grace_period` は 40 秒なので、Compose が正常な停止処理を中断することはありません。
3. **worker は最後** に更新します。新しいイベント形式を先に生成し、次に新しい形式を期待する consumer を動かすためです。worker はすぐにジョブ取得を止め、120 秒間処理を続けます。完了できないジョブは他の場所で再取得されます。すべてのジョブが冪等なので安全です。scheduler は次の起動時にリーダーを引き継ぎます。

単一ホストでは Compose が各コンテナを順番に置き換えるため、サービスごとに短い停止があります。停止をなくすには、独自プロキシの背後で Web 層を 2 コンテナ実行します (公開ポートなしの 2 つ目の Web サービスをオーバーライドファイルで追加)。正常状態を確認してから 1 つずつ再作成します。

## 複数ホストまたはオーケストレーター <!--quire:several-hosts-or-an-orchestrator-->

同じ順序で実行します。1 つのジョブで一度だけマイグレーションし、Web 層は追加台数 1、利用不能台数 0 で段階的に更新してから worker を更新します。準備状態プローブは `/readyz`、生存状態プローブは `/healthz` を使います。

テナントごとの専用 DB がある場合、`migrate` はまず制御 DB を移行し、次に `ops.tenant_database` にある各 DB を個別のロックを取得して順番に移行します。1 つのテナント DB が失敗しても他は続行します。すべて完了した後、マイグレーション履歴を比較し、制御 DB と同じマイグレーションが適用されていない DB を列挙して、終了コード 0 以外で終了します。worker は固定テナントのジョブを登録先 DB から処理するため、同じコマンドで各 DB のキューテーブルも作成します。

```sh
bun apps/worker/src/migrate.ts   # what the Compose step runs
bun run db:migrate:all                            # the same, from a checkout
```
通常のマイグレーションと初回セットアップでは、Quire運営者の正規の英語法務文書も`ops.platform_policy_version`にインストールされます。インストーラはべき等です。欠落している英語本文と、マイグレーションがシードした正確なプレースホルダー本文のみが置換されます。シードはアーカイブされ、新しい公開バージョンが挿入されます。過去の承認参照と本文は保持されます。ドラフトを含む、運営者が実際に作成したバージョンはすべて保持され、プラットフォームのポリシーコンソールで管理する必要があります。テナントのポリシードキュメント、バージョン、同意がこの切り替えで変更されることはありません。これは運営者テキストの公開であり、法的認証でも約束の自動履行でもありません。


各専用 DB には登録名で接続します。`env:QUIRE_DB_NORTHWIND_URL` として登録した DB には次が必要です。

| 変数 | 用途 |
| --- | --- |
| `QUIRE_DB_NORTHWIND_URL` | Web 層と worker 用アプリケーションロール |
| `QUIRE_DB_NORTHWIND_URL_MIGRATOR` | このコマンドと移動処理用の migrator ロール |
| `QUIRE_DB_NORTHWIND_URL_SUPERUSER` | 任意。マイグレーション前に初期設定 (ロール、スキーマ、ヘルパー) を再適用 |

`_MIGRATOR` 接続のない登録済み DB はスキップせず、失敗として報告します。制御 DB の移行後に Web 層を更新できます。テナント DB の遅れが 1 時間なら警告、1 日ならページ通知です。

## pgvector <!--quire:pgvector-->

マイグレーション 0264 以降、サーバーに拡張機能がある場合、grounding コーパスでは pgvector HNSW インデックスを使います。Compose の `postgres` サービスは拡張機能込みでビルドされます (`docker/postgres.Dockerfile`)。イメージ切り替え後の最初の `migrate` は superuser bootstrap で拡張機能を作り、0264 が生成ベクター列を追加してインデックスを構築します。列の追加では排他ロックのもと `app.ai_chunk` を一度書き換えるため、grounding のリクエストはその間待機します。他の処理はこのテーブルを使いません。

pgvector がないサーバーでは 0264 は通知をログに記録して何も変更せず、検索は正確検索のままです。pgvector が 0.8 より古い場合、列とインデックスは作成されますが、拡張機能を更新 (`alter extension vector update`) するまで正確検索を使います。フィルター付き HNSW スキャンには 0.8 の反復スキャン機能が必要だからです。未導入サーバーで後から有効にするには、拡張機能をインストールし、bootstrap を再実行する (または superuser で `create extension vector` を実行する) か、`quire_migrator` として次を実行します。

```sql
set maintenance_work_mem = '1GB';  -- the HNSW build is much faster in memory
select ops.ai_chunk_enable_vector_index();
```

冪等な処理で `enabled` または `unavailable` を返します。各専用テナント DB でも実行してください。

## ロールバック <!--quire:rolling-back-->

**コード** のロールバックはいつでも可能です。`QUIRE_RELEASE` を前のタグに戻して `up -d` を実行します。リリース内ではスキーマが前後どちらのバージョンにも互換性を持つためです。

**スキーマ** のロールバックはできません。取り消せない変更と復旧方法は次のとおりです。

| 元に戻せないもの | 復旧方法 |
| --- | --- |
| 列を削除した縮約マイグレーション | 削除前の時点に新しい DB へ復元し、データを抽出して統合 |
| インプレースのデータ変更 | 同様に復元し、その後の書き込みを調整 |
| 送信済み webhook とイベント | 削除せず、補償イベントを送信 |
| 送信済みメール | 人がフォローアップを書く |
| 監査ハッシュチェーン | 書き換えず、訂正エントリを追加 |

そのため縮約マイグレーションは単独リリースにします。復元時に明確な境界を保てます。

## アップグレードの確認 <!--quire:checking-the-upgrade-->

```sh
docker compose -f docker/compose.yaml ps           # every service healthy
curl -fsS http://localhost:8080/readyz             # ready, and what is configured
docker compose -f docker/compose.yaml logs migrate # the migrations applied
```

Source: https://docs.quirelms.com/ja/ops/upgrade/index.mdx
