Redmineのバージョンアップ（Redmine3.2 -> 4.1とRedmica1.2への切り替え）その３（移行）

はじめに

- 概要　調査・検討 / 構築 / 移行 / 番外編 のうちの、移行です
- バージョンアップに伴う他作業も含めてシステム移行として扱います

## 記事の全体構成
- [その１ 概要・調査検討](https://qiita.com/ssugimoto/items/6fee7bbf0d7c07ef9321)
- [その２ 構築](https://qiita.com/ssugimoto/items/c2b90c0b745f15575a71)
- その３ 移行（このページ）
- [その４ Redmine バージョンアップにおける番外編](https://qiita.com/ssugimoto/items/e62472e74fa7b0a1154f)

--- 

## 事前
- システム移行は、計画完了で８割は終わる、後は実作業とトラブル対応
- リハーサル等を実施し、作業ごとの時間を計測しておく
- 簡易なタイムスケジュールを作成しておく
    - どの作業に、XX分 
- 同時並行はできないため、事前に停止日時を調整・アナウンスしておく
    - 利用者が少ない段階では、大きな調整は不要。利用者が多くなると調整が難航する
    - 何らかのシステムとリリースが絡むとRedmineを止められないケースがある
    - 翌日が休みの場合は控える、金曜リリースは控える
- 切り戻しプランを考えておく
    - システム切替え等は、中止がありえるため以前の状態で稼働させることが必要なケースがある
    - 今回はVMWareかつ別のインスタンスへ切替えるため切り戻しはIPを戻す程度
    - 同じインスタンス内でバージョンアップ等する場合は戻せることを確認しておく。また、VMWareのスナップショット機能を使うならば、いったんOSシャットダウンしてから取得すると高速に取得できる。
    - MySQLのmysqldumpはVMWareのスナップショット機能で戻せない場合のデータ復旧用。dumpしたファイルは別の場所に置くこと
- 稼働確認の確認手順、項目を洗い出しておくこと

- IP アドレスの例です、現行と新のIP切替えの想定表

|  移行前  |  IPアドレス  | 
| ---- | ---- |---- |---- |
|  移行元（現行）|  192.168.0.8  |
|  移行先 （新） |  192.168.0.10  |


|  移行後  |  IPアドレス  | コメント  |
| ---- | ---- |---- |---- |
|  移行元（現行）|  192.168.0.11  |何らか調査用に別IPアドレスに変更して見られるよにしておく|
|  移行先 （新） |  192.168.0.8  |現行のIPに変更することで、外側からのルーティング等の変更不要|

---

## タイムスケジュール

- 前提、Redmine4.1.1の後のRedmica1.2が動作検証していたRedmine関連ファイル・ディレクトリ等はそのままあること
- MySQLのデータ、files以外は全て移行後と同じ状態
- Redmineでは、初期の頃は filesのファイルがfilesディレクトリ直下にファイルが置かれていたが、yyyy/mm のディレクトリにアップロードされるようになったため、差分や増分がわかりやすくなっている
    - 移行の１ヶ月前くらいからのファイルを差分移行（上書き）することでfilesの移行容量は減らすことができる
    - 日々 rsync等で移行する方法もある、rsync使う場合は移行時に最終のrsyncを実行すれば良い
    - syncの注意点は、今回の環境移行では発生しないが、相互にrsyncすると 移行完了後に現行（移行後に使わない）を残したままにしておくと、新の方が消えることがありえるので注意

- 以下のタイムスケジュールを策定（サンプル）

| 対象  |  時間  | 所要時間  | 内容  |
| ---- | ---- |---- |---- |
|  新  |  事前作業  |TD  |データベースは残したまま、テーブルをdropしておく。データベースへのアクエス権限許可設定があるため、設定をいかすためテーブル削除まで  |
|  新  |  事前作業  |TD  |MySQLのconfとRedmineのdatabase.ymlは、utf8に戻しておく、移行元はutf8で、マイグレーション完了後にutf8mb4にする、Redmineが使うデータベースはutf8mb4のままでも良い |
|  新  |  事前作業  |TD  |filesの事前移行、rsync等で対応するか、事前に大量移行しておくか  |
|  現行  | XX:XX  |1  |停止アナウンス  |
|  現行  | XX:XX  |1  |Apacheの停止、ログを見てアクセスないことを確認する  |
|  現行  | XX:XX  |5  |MySQLのデータベースのバックアップ mysqldumpの実行。結果ファイルを新へ転送、一部のシーケンスやテーブルのレコード件数を移行時のチェックに使う  |
|  現行  | XX:XX  |5  |filesの特定ディレクトリを圧縮し、新へ転送  |
|  新  |  XX:XX  |15  |mysqldumpをインポート  |
|  新  |  XX:XX  |1  |インポート結果の確認（テーブル数、レコード件数等） |
|  新  |  XX:XX  |10  |ALTERを実行（カラムのデフォルト値変更） |
|  新  |  XX:XX  |10  |db:migrateを実行 |
|  新  |  XX:XX  |5  |プラグインのマイグレーションを実行 |
|  新  |  XX:XX  |1  |シークレットキー |
|  新  |  XX:XX  |1  |キャッシュクリア |
|  新  |  XX:XX  |15  |Redmineが使うテーブルとDatabaseの文字エンコーディング変更、Redmineのdatabase.ymlでのエンコード変更|
|  新  |  XX:XX  |1  |Apache起動 |
|  新  |  XX:XX  |15  |ログイン、チケット一覧 程度の動作確認 |
|  新  |  XX:XX  |1  |テーマの変更 |
|  新  |  XX:XX  |1  |プラグインの設定変更 |
|  新  |  XX:XX  |15  |プラグイン等の動作確認 |
|  新  |  XX:XX  |5  |Git、SVN連けい |
|  新  |  XX:XX  |15  |プラグイン切替えした代替の設定や変更 |
|  新  |  XX:XX  |10  |新の方に現行から転送したfilesの特定ディレクトリを反映（上書き） |
|  新  |  XX:XX  |5  |動作確認 |
|  新  |  XX:XX  |1  |新に切替えるか判断 |
| 現行  |  XX:XX  |1  |IP変更する |
|  新  |  XX:XX  |1  |IPを現行のIPに変更する |
|  新  |  XX:XX  |1  |Apache reload 、外側インターネット越しに動作確認 |
|  新  |  XX:XX  |1  |移行完了のアナウンス |
| 現行  |  XX:XX  |1  |cronを止める、後日にOSシャットダウン |
|  新  |  XX:XX  |--  |翌日等に、バックアップ、ログ等の確認、モニタリング |

---

## 移行作業結果

- タイムスケジュール想定通り
- スケジュール上は余裕をもっていたが、稼働確認を入念にしたたため想定通りの終了時間になった
- アナウンス上での停止時間は90分

---

# 作業時の小手先スクリプト等

## MySQLのmysqldumpのエクスポートとインポート

- 現行でエクスポート、gz圧縮も合わせてしている、ファイル出力先の容量に気をつける

```
mysqldump -uユーザ -pパスワード --no-tablespaces 対象データベース | gzip > /var/tmp/redmine_`date +%y_%m_%d`.gz
```

- scpコマンドで現行から新に転送

コマンド割愛

- 新でRedmineが利用するデータベースはcreateせず、Redmica1.2で稼働させていたものが存在する前提

```
cd XXX
mysql -u ユーザー（rootでも可） -pパスワード（後入力でも可） インポートするデータベース < redmine_21_04_XX
```

- テーブル数

インポート後は、75テーブル、Redmine4.1にバージョンアップすると76になる
`custom_values` のテーブルに yyyymmddが付与されたテーブルの数により変わる


---

## MySQLの特定のデータベースのテーブル一覧をDropするSQL

https://www.cyberciti.biz/faq/how-do-i-empty-mysql-database/ を参考に
`mysql-drop-tableForRedmine.sh` のようなファイル名として

```
#!/bin/bash
MUSER="$1"
MPASS="$2"
MDB="$3"

# Detect paths
MYSQL=$(which mysql)
AWK=$(which awk)
GREP=$(which grep)
 
if [ $# -ne 3 ]
then
  echo "Usage: $0 {MySQL-User-Name} {MySQL-User-Password} {MySQL-Database-Name}"
  echo "Drops all tables from a MySQL"
  exit 1
fi
 
TABLES=$($MYSQL -u $MUSER -p$MPASS $MDB -e 'show tables' | $AWK '{ print $1}' | $GREP -v '^Tables' )
 
for t in $TABLES
do
  echo "Deleting $t table from $MDB database..."
  ## $MYSQL -u $MUSER -p$MPASS $MDB -e "drop table $t" 
done
```

`##` の コメント外すとdrop tableされる

- 実行

```
./mysql-drop-tableForRedmine.sh user password database
```

---

## MySQLのALTER文を生成

- MySQL 内 redmineが使うデータベースのテーブル一覧からALTER文を作成
- `(`の記号からそのまんま実行する

```
# (mysql -uXXXX -p データベース名 -e "show tables" --batch --skip-column-names | xargs -I{} echo 'alter table `'{}'` convert to character set utf8mb4;') > /tmp/alters_table_CHARSET.sql
Enter password: 
```

結果ファイル

```
cat /tmp/alters.sql 
alter table `ar_internal_metadata` convert to character set utf8mb4;
alter table `attachments` convert to character set utf8mb4;
alter table `auth_sources` convert to character set utf8mb4;
alter table `boards` convert to character set utf8mb4;
alter table `changes` convert to character set utf8mb4;
alter table `changeset_parents` convert to character set utf8mb4;
alter table `changesets` convert to character set utf8mb4;

・・・
・・
```

## MySQLのテーブルの文字エンコーディングを確認する

```
$ mysql -uユーザ -p 対象データベース

> SELECT table_name,table_collation FROM information_schema.tables WHERE table_schema = DATABASE() ;
```

---

## ファイル所有者・パーミッション

root作業が多いため、要所要所・最後に chown で所有者を Redmineを実行するユーザー（apache）に切替えすること

---

## Redmineにログインした後の不要なニュースの削除

- 既に終了、アーカイブしたプロジェクト内のニュースが表示されてしまう。プロジェクトを開いてニュースを編集してといった作業をしなくても表示を消す方法

```
select * from news ;
id, project_id, title, created_on
```

を見ると、Redmineの内部的なプロジェクトID番号、いつ作成したのかがわかる
このテーブルで不要なレコードを消せば良い
全て不要だったので、

```
Delete From news;
```

にて消した

---

## RedMica1.2へ

http://blog.redmine.jp/articles/mica-1_2/migration-from-redmine/

- RedMica1.2 では Redmine3.4 or 4.0 または4.1からのバージョンアップが想定だった模様
- おそらく、メジャーバージョンでの最終のものからの移行想定と思われる。