AWS Mattermost 開発者ブログ

MattermostのMySQLからPostgreSQLへのマイグレーションをやってみた!!

こんにちは、moriです。

はじめに

先日、Mattermost v10が公開されましたが、MySQLによる新規構築がサポート外になるなどの変化があり、次のメジャーバージョンアップではMySQLが非推奨になる見込みです。

弊社でも、長らくMySQLでMattermostを運用してきましたが、これを機にPostgreSQLへの移行を検討することにしました。
なお、弊社では2つのMattermostインスタンスを運用しており、そのうち1つは投稿数が200万件を超える大規模なものです。

本記事では、移行にかかった時間や作業の流れについても解説していきます。

マイグレーションの流れ

以下の手順に沿って進めていきます。

  1. マイグレーションツール実行サーバの構築
  2. 新規Mattermostサーバの構築
  3. マイグレーションツールの実行
  4. 起動確認
  5. ELBの切り替え

基となる手順はMattermost公式の「Automated PostgreSQL migration」を参考にしました。


Step 1. マイグレーションツール実行サーバの構築

最初に、マイグレーションツールを動かすためのサーバを用意します。
弊社ではAWSのEC2インスタンスを利用し、以下のスペックで構築しました。

構築スペック

  • スペック:s3.medium
  • OS: AmazonLinux2023
  • 事前にインストール:gitmysqlclientpsql(PostgreSQL Client)

使用するマイグレーションツールには、「migration-assist」と「pgloader」を使用します。

  • migration-assist: MySQLからPostgreSQLへデータをスムーズに移行するための専用ツール
  • pgloader: MySQLのデータを高速でPostgreSQLに移行するオープンソースツール

「migration-assist」のセットアップ

まず、GitHubから「migration-assist」をダウンロードします。

$ sudo mkdir /opt/migration-assist
$ cd /opt/migration-assist
$ sudo wget https://github.com/mattermost/migration-assist/releases/download/v0.3/migration-assist-Linux-x86_64.tar.gz
$ sudo tar -zxvf migration-assist-Linux-x86_64.tar.gz

「pgloader」のセットアップ

pgloaderのインストールにはsbcl(Steel Bank Common Lisp)が必要となります。以下がその手順です。

  1. sbclのバイナリファイルをダウンロードし、スクリプトでインストールします。
$ wget https://sourceforge.net/projects/sbcl/files/sbcl/2.3.6/sbcl-2.3.6-x86-64-linux-binary.tar.bz2
$ tar -xvf sbcl-2.3.6-x86-64-linux-binary.tar.bz2 cd sbcl-2.3.6-x86-64-linux
$ sudo ./install.sh
$ sbcl --version
  1. pgloaderのビルドに必要なツールをインストールします。
$ sudo yum install -y make gcc clang
$ sudo tee /etc/yum.repos.d/epel.repo <<EOL[epel]
name=Extra Packages for Enterprise Linux 9 - \$basearch
baseurl=https://download.fedoraproject.org/pub/epel/9/Everything/\$basearch/
enabled=1
gpgcheck=0
EOL

$ sudo yum clean all
$ sudo yum install -y freetds freetds-devel
  1. ソースコードからpgloaderをビルドし、インストールします。
$ git clone https://github.com/dimitri/pgloader.git 
$ cd pgloader
$ make pgloader 
$ sudo cp build/bin/pgloader /usr/local/bin/
$ sudo chmod +x /usr/local/bin/pgloader

インストール後、pgloaderコマンドが動作するか確認します。

$ pgloader --version
pgloader version "3.6.70f3557"
compiled with SBCL 2.3.6

Step 2. 新規Mattermostサーバの構築

移行先のMattermostを構築します(詳細なEC2やPostgreSQLの設定手順については割愛します)。
マイグレーションツール実行サーバから接続できるよう、pg_hba.confに設定を追加します。
下記を設定後にPostreSQLを再起動し、マイグレーションサーバからPostgresに接続できることを事前に確認してください。

例: マイグレーションツール実行サーバのIPが172.1.2.34/32の場合

/var/lib/pgsql/data/pg_hba.conf
  :
host    all             all             172.1.2.34/32           md5    #追加
  :

Step 3. マイグレーションツールの実行

※接続情報は適宜読み替えてください。

"<MYSQL_DSN>"は移行元のMYSQLへの接続情報になります。例 'xxuser:password@tcp(address:3306)/mattermost'
"<POSTGRES_DSN>"は移行先のPosrgresSQLへの接続情報となります。例 'postgres://xxuser:password@address:5432/mattermost?sslmode=disable'

  1. 移行元のMySQLデータベースのスキーマ確認
$ /opt/migration-assist/migration-assist mysql "<MYSQL_DSN>"

サンプル出力:

$ /opt/migration-assist/migration-assist mysql 'xxuser:password@tcp(address:3306)/mattermost'

2024-11-05 23:26:16 pinging mysql...
2024-11-05 23:26:16 connected to mysql successfully...
2024-11-05 23:26:16 running checks for artifacts...
2024-11-05 23:26:16 a fix is required for: schema_migrations
2024-11-05 23:26:16 4 checks been made, 1 fix(es) is required for artifacts
2024-11-05 23:26:16 running checks for unicode...
2024-11-05 23:26:45 a fix is required for: linkmetadata_data
2024-11-05 23:27:20 a fix is required for: posts.props
2024-11-05 23:27:20 11 checks been made, 2 fix(es) is required for unicode
2024-11-05 23:27:20 running checks for varchar...
2024-11-05 23:27:20 8 checks been made, all good for varchar
2024-11-05 23:27:20 running checks for varchar-extended...
2024-11-05 23:27:44 a fix is required for: linkmetadata.url
2024-11-05 23:27:44 12 checks been made, 1 fix(es) is required for varchar-extended

必要に応じて--fix-artifacts --fix-unicode --fix-varcharのオプションで修正を行ってください。

$ /opt/migration-assist/migration-assist mysql 'xxuser:password@tcp(address:3306)/mattermost' --fix-artifacts --fix-unicode --fix-varchar

すべてのチェックにクリアし場合は下記のような出力になります。※すべてall goodで結果が返されます。

$ /opt/migration-assist/migration-assist mysql 'xxuser:password@tcp(address:3306)/mattermost'

2024-11-03 23:10:02 pinging mysql...
2024-11-03 23:10:02 connected to mysql successfully...
Output file already exists, do you want to overwrite it? [y/N]: y
2024-11-03 23:10:09 running checks for artifacts...
2024-11-03 23:10:09 4 checks been made, all good for artifacts
2024-11-03 23:10:09 running checks for unicode...
2024-11-03 23:10:10 11 checks been made, all good for unicode
2024-11-03 23:10:10 running checks for varchar...
2024-11-03 23:10:10 8 checks been made, all good for varchar
2024-11-03 23:10:10 running checks for varchar-extended...
2024-11-03 23:10:10 12 checks been made, all good for varchar-extended

  1. 移行先のPostgreSQLデータベーススキーマ作成
$ /opt/migration-assist/migration-assist postgres "<POSTGRES_DSN>" --run-migrations --mattermost-version="<MATTERMOST_VERSION>"
# mattermost v9.11.0の場合の実行例となります

$ /opt/migration-assist/migration-assist postgres 'postgres://xxuser:password@address:5432/mattermost?sslmode=disable' --run-migrations --mattermost-version="9.11.0"
  1. pgloader設定の生成と実行
$ /opt/migration-assist/migration-assist pgloader --mysql="<MYSQL_DSN>" --postgres="<POSTGRES_DSN>" > migration.load
$ pgloader migration.load > migration.log
  1. 全文インデックスを復元する
$ /opt/migration-assist/migration-assist postgres post-migrate "<POSTGRES_DSN>"
  1. プラグイン関連のデータの移行する
$ /opt/migration-assist/migration-assist pgloader boards --mysql="<MYSQL_DSN>" --postgres="<POSTGRES_DSN>" > boards.load
$ /opt/migration-assist/migration-assist pgloader playbooks --mysql="<MYSQL_DSN>" --postgres="<POSTGRES_DSN>" > playbooks.load
$ /opt/migration-assist/migration-assist pgloader calls --mysql="<MYSQL_DSN>" --postgres="<POSTGRES_DSN>" > calls.load

$ pgloader boards.load > boards_migration.log
$ pgloader playbooks.load > playbooks_migration.log
$ pgloader calls.load > calls.log
  1. 新しい PostgreSQL データベースを利用するように Mattermost を構成する

今回は別サーバにMattermost と データベースを移行していきます。Mattermostとデータベースを分けている場合はMattermostの移行は不要でDSNの定義を変更ください。

# Mattermostを新サーバへ移行します
# 移行元サーバで実施します
$ sudo tar -czvf /tmp/mattermost_backup.tar.gz /opt/mattermost
$ scp /tmp/mattermost_backup.tar.gz user@<NEW_SERVER_IP>:/tmp

# 移行先サーバで実施します
$ sudo tar -xzvf /tmp/mattermost_backup.tar.gz -C /
$ sudo useradd --system --user-group mattermost
$ sudo chown -R mattermost:mattermost /opt/mattermost
$ sudo chmod -R g+w /opt/mattermost

Mattermostの起動ファイルを作成する

$ sudo touch /lib/systemd/system/mattermost.service
$ sudo vi /lib/systemd/system/mattermost.service  # 以下の内容を記載します
[Unit]
Description=Mattermost
After=network.target
[Service]
Type=notify
ExecStart=/opt/mattermost/bin/mattermost
TimeoutStartSec=3600
KillMode=mixed
Restart=always
RestartSec=10
WorkingDirectory=/opt/mattermost
User=mattermost
Group=mattermost
LimitNOFILE=49152
[Install]
WantedBy=multi-user.target

systemctl をリロードします。

$ sudo systemctl daemon-reload

Mattermost のconfig.jsonファイルのDSNを書き換えます。

        :
    "DriverName": "postgres",
    "DataSource": "postgres://xxuser:password@localhost/mattermost?sslmode=disable\u0026connect_timeout=10\u0026binary_parameters=yes",
        :


Step 4. Mattermostの起動

Mattermostのconfig.jsonにて接続設定を修正後、起動確認を行います。

$ systemctl start mattermost
$ systemctl status mattermost

必要な設定変更を終えたら、自動起動を有効にします。

$ systemctl enable mattermost

なお、起動時にMattermostがDBに接続できないエラーが発生することがありますが、公式ドキュメントにトラブルシューティングが記載されていますので、参考にしてください。

実際に弊社の移行時にも発生しました。どうやらsearch_pathの設定がおかしいことになっていました。以下のような手順で回避しています。

mattermost=> \dt
リレーションが見つかりませんでした。

mattermost=> SELECT usename, setting FROM pg_user u
JOIN pg_settings s ON u.usename = current_user
WHERE name = 'search_path';
 usename  |           setting
----------+-----------------------------
 xxuser   | """""""$user"""", public"""


mattermost=> ALTER DATABASE mattermost SET search_path TO public, "$user";
mattermost=> ALTER USER xxuser SET search_path TO public, "$user";

mattermost=> SELECT usename, setting FROM pg_user u
JOIN pg_settings s ON u.usename = current_user
WHERE name = 'search_path';
 usename  |     setting
----------+-----------------
 xxuser   | public, "$user"


ttermost=> \dt
                         リレーション一覧
 スキーマ |               名前               |  タイプ  |  所有者
----------+----------------------------------+----------+----------
 public   | audits                           | テーブル | mmuseren
 public   | bots                             | テーブル | mmuseren
 public   | calls                            | テーブル | mmuseren
  ;

Step 5. ELBの切り替え

新しいMattermostをターゲットグループに追加し、旧Mysql環境のMattremostを除外します。(詳細な設定手順については割愛します)。

その他

200万件を実施した際の時間についても共有させていただきます。
なお、ステップ3で実施した、migration.logの最後にデータ移行にかかった時間がサマリ化されています。

                         table name     errors       rows      bytes      total time
------------------------------------  ---------  ---------  ---------  --------------
                         before load          0          4                     0.160s
                     fetch meta data          0         67                     0.240s
                   Drop Foreign Keys          0          4                     0.020s
------------------------------------  ---------  ---------  ---------  --------------
                    mattermost.posts          0    2213848   962.8 MB      16m25.526s
             mattermost.linkmetadata          0    1217760   678.0 MB       3m56.199s
                     mattermost.jobs          0      66736     8.9 MB          6.330s
                   mattermost.audits          0      54530     7.3 MB          5.830s
                  mattermost.threads          0       8320     1.1 MB          1.500s
                    mattermost.emoji          0       2551   231.5 kB          1.910s
            mattermost.postspriority          0        779    46.4 kB          2.230s
              mattermost.teammembers          0        288    19.8 kB          2.580s
                   mattermost.status          0        168     8.9 kB          3.240s
         mattermost.incomingwebhooks          0         18     3.4 kB          3.620s
                 mattermost.commands          0          5     1.8 kB          3.940s
                mattermost.oauthapps          0          2     0.6 kB          4.320s
              mattermost.compliances          0          0                     4.680s
                 mattermost.fileinfo          0      10614    34.2 MB          8.380s
               mattermost.groupteams          0          0                     5.010s
  mattermost.persistentnotifications          0          0                     5.320s
  mattermost.retentionidsfordeletion          0          0                     5.740s
                  mattermost.schemes          0          0                     6.130s
           mattermost.sharedchannels          0          0                     6.500s
               mattermost.usergroups          0          0                     6.980s
           mattermost.channelmembers          0       4077   940.9 kB          0.440s
        mattermost.sidebarcategories          0        745   109.2 kB          0.670s
                 mattermost.sessions          0        289    69.3 kB          0.920s
                   mattermost.drafts          0        188    58.3 kB          1.300s
                    mattermost.roles          0         22    22.5 kB          1.590s
         mattermost.useraccesstokens          0         10     1.0 kB          1.860s
          mattermost.oauthaccessdata          0          2     0.4 kB          2.150s
          mattermost.commandwebhooks          0          0                     2.490s
             mattermost.groupmembers          0          0                     2.930s
 mattermost.outgoingoauthconnections          0          0                     3.250s
           mattermost.remoteclusters          0          0                     3.600s
   mattermost.retentionpoliciesteams          0          0                     4.080s
       mattermost.sharedchannelusers          0          0                     4.550s
           mattermost.uploadsessions          0          0                     4.400s
        mattermost.threadmemberships          0      19920     1.6 MB          1.840s
     mattermost.channelmemberhistory          0       4430   308.5 kB          0.650s
                 mattermost.channels          0        970   204.8 kB          1.440s
   mattermost.productnoticeviewstate          0        470    28.3 kB          0.510s
                    mattermost.users          0        196   109.7 kB          1.410s
                  mattermost.systems          0         65     2.7 kB          1.250s
                    mattermost.teams          0         12     1.8 kB          1.520s
         mattermost.outgoingwebhooks          0          3     1.0 kB          1.630s
         mattermost.clusterdiscovery          0          0                     1.610s
            mattermost.groupchannels          0          0                     1.600s
              mattermost.notifyadmin          0          0                     1.650s
            mattermost.postreminders          0          0                     1.750s
mattermost.retentionpolicieschannels          0          0                     1.910s
     mattermost.sharedchannelremotes          0          0                     1.730s
                   mattermost.tokens          0          0                     1.890s
                mattermost.reactions          0      25765     3.0 MB          1.010s
              mattermost.preferences          0       6980   608.7 kB          0.460s
          mattermost.sidebarchannels          0       1538   167.8 kB          0.240s
      mattermost.pluginkeyvaluestore          0        547     8.5 MB          1.010s
           mattermost.publicchannels          0        244    29.6 kB          0.880s
           mattermost.recentsearches          0        112    17.4 kB          0.430s
                     mattermost.bots          0         20     2.2 kB          0.850s
            mattermost.oauthauthdata          0          3     0.6 kB          0.830s
         mattermost.channelbookmarks          0          0                     0.790s
            mattermost.desktoptokens          0          0                     0.790s
                 mattermost.licenses          0          0                     0.730s
     mattermost.postacknowledgements          0          0                     0.950s
        mattermost.retentionpolicies          0          0                     1.000s
 mattermost.sharedchannelattachments          0          0                     0.940s
           mattermost.termsofservice          0          0                     0.920s
       mattermost.usertermsofservice          0          0                     0.920s
------------------------------------  ---------  ---------  ---------  --------------
             COPY Threads Completion          0          8                 16m25.476s
                     Reset Sequences          0          0                     0.350s
                 Create Foreign Keys          0          2                     0.060s
                     Set Search Path          0          1                     0.020s
                    Install Comments          0          0                     0.000s
                          after load          0          4                     0.190s
------------------------------------  ---------  ---------  ---------  --------------
                   Total import time          ✓    3642227     1.7 GB      16m26.096s

メインの投稿データであるmattermost.postsは17分弱かかっていることがわかります。

その他の手順などの実施時間やトラブルシュートも対応したりしながらでの実施でしたので、今回、弊社で実施した際は、トータルで2時間程サービス停止させてしまいました。

データ移行はMattermostの停止を伴いますので、移行計画をする際のご参考にしていただければと思います。


Recruit

ディーメイクでは各ポジションで一緒に働く仲間を募集中! エンジニア、デザイナー、ディレクターなど、多彩な職種があります。
一緒に成長していきましょう!

最新記事

おすすめ記事リンク

-AWS, Mattermost, 開発者ブログ