SQLite 版 Redmine のレスポンス改善

SQLite は端的に言うと以下の特徴を持つRDBMSです。

  • フリー
    Public Domain と呼ばれるライセンスで個人・商用利用問わず無償です。
  • 環境に依存しない
    APIや接続用のライブラリがあれば(システムへのインストール作業なしに)利用可能。
  • 高速 = 単純
    複雑な機能を有していない代わりに高速です。
  • DB = ファイル
    DB が1ファイルのため管理が容易です。
  • INSERT, UPDATE, DELETE は ファイルロックされる
    ※ロック中は当該 DB への SELECT も不可になる。

SQLite は実運用で使うと、DB がロックされやすい性質があります。
その際の解決策としては、以下の2つがあります。

  • SQLite のタイムアウト時間を長く設定する
    すぐエラーを返さずに Wait してくれます。
  • 高速な記憶装置上に置く
    ロック時間はデバイス(ファイルシステム)に依存するので、SSD など高速な記憶装置に移動することで影響を小さくできます。

手元に高速な USBメモリがあったのでそこに当該 DB を移動して高速化を図ることにしました。

base on RUF2-S512-WH

SLCを採用し、且つ2チップ同時転送で高速化したUSB2.0メモリ

目次

Redmine 高速化

DB(SQLite)用に高速デバイス(今回は USBメモリ)を用意して、入れ替えます。

M/W デバイス
DB USBメモリ
DB以外 microSD

USBメモリのフォーマット

パーティション作成

fdisk コマンドで領域を確保します。

$ sudo fdisk /dev/sda

Welcome to fdisk (util-linux 2.29.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x0ae2bbf1.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 
First sector (2048-1003519, default 2048): 
Last sector, +sectors or +size{K,M,G,T,P} (2048-1003519, default 1003519): 

Created a new partition 1 of type 'Linux' and of size 489 MiB.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

/dev/sda1 が作成されました。

$ lsblk /dev/sda
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    1  490M  0 disk 
└─sda1   8:1    1  489M  0 part

ファイルシステム作成

今回は ext3 で作成しました。

$ sudo mkfs -t ext3 /dev/sda1
mke2fs 1.43.4 (31-Jan-2017)
Creating filesystem with 500736 1k blocks and 125488 inodes
Filesystem UUID: fe75bf02-90ed-4823-b319-437ffcf4b607
Superblock backups stored on blocks: 
    8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done 

デバイスの属性を確認

UUID(場合によって PARATUUID)を確認します。

$ blkid /dev/sda1
/dev/sda1: UUID="fe75bf02-90ed-4823-b319-437ffcf4b607" SEC_TYPE="ext2" TYPE="ext3" PARTUUID="0ae2bbf1-01"

USBメモリのマウント

マウントするディレクトリを作成

$ ls /media/
$ mkdir /media/usb512

マウント情報を記述

/etc/fstab ファイルに記述した後「mount -a」でテストしておきます。

$ diff -u /tmp/fstab /etc/fstab 
--- /tmp/fstab  2019-03-13 14:11:20.431494925 +0000
+++ /etc/fstab  2019-03-13 14:18:44.358482664 +0000
@@ -1,2 +1,3 @@
 UUID=b065c39b-25c7-4379-9e17-0f511ae83aa4 / ext4 defaults,noatime,nodiratime,commit=600,errors=remount-ro 0 1
 tmpfs /tmp tmpfs defaults,nosuid 0 0
+UUID=fe75bf02-90ed-4823-b319-437ffcf4b607 /media/usb512 ext3 defaults,noatime 0 1

$ sudo mount -a
$ mount | grep sda
/dev/sda1 on /media/usb512 type ext3 (rw,noatime)

DB移動

USBメモリに DB格納用ディレクトリを作成

SQLite ファイルを置くディレクトリを USBメモリに作成します。
※パーミッションはあとで www-data に置換します。

$ mkdir /media/usb512/redmine_sqlite3
$ ls -lhd /media/usb512/redmine_sqlite3/
drwxr-xr-x 2 root root 1.0K Mar 13 14:22 /media/usb512/redmine_sqlite3/

移動前にサービス停止

$ sudo systemctl stop apache2

DB 実ファイルを確認

設定ファイル(database.yml)で場所を確認して、実ファイルを念の為チェックしておきます。

$ cat /etc/redmine/default/database.yml | grep sqlite
  adapter: sqlite3
  database: /var/lib/dbconfig-common/sqlite3/redmine/instances/default/redmine_default

$ ls -lh /var/lib/dbconfig-common/sqlite3/redmine/instances/default/redmine_default
-rw-rw---- 1 root www-data 776K Mar 12 11:52 /var/lib/dbconfig-common/sqlite3/redmine/instances/default/redmine_default

DBファイル移動

USBメモリにデータを移動します。

  • 移動
$ mv /var/lib/dbconfig-common/sqlite3/redmine/instances/default/redmine_default /media/usb512/redmine_sqlite3/
  • 移動の確認
$ ls  /media/usb512/redmine_sqlite3/
redmine_default
  • シンボリックリンク作成
$ sudo ln -s /media/usb512/redmine_sqlite3/redmine_default /var/lib/dbconfig-common/sqlite3/redmine/instances/default/redmine_default
  • シンボリックリンク確認
$ ls -lh /var/lib/dbconfig-common/sqlite3/redmine/instances/default/
total 0
lrwxrwxrwx 1 root root 45 Mar 13 14:26 redmine_default -> /media/usb512/redmine_sqlite3/redmine_default

権限変更

パーミッションを apacheユーザ(www-data)に変更します。

$ ls -lh /media/usb512/redmine_sqlite3/redmine_default
-rw-rw---- 1 root www-data 776K Mar 13 14:01 /media/usb512/redmine_sqlite3/redmine_default

$ sudo chown -R www-data:www-data /media/usb512

$ ls -lh /media/usb512/redmine_sqlite3/redmine_default
-rw-rw---- 1 www-data www-data 776K Mar 13 14:27 /media/usb512/redmine_sqlite3/redmine_default

サービス起動

$ sudo systemctl start apache2

稼働確認

稼働確認して問題ないことを確認します。

エラーになった場合は、ログを確認します。

$ cat /etc/apache2/apache2.conf | grep error
# configuration, error, and log files are kept.
# ErrorLog: The location of the error log file.
# container, error messages relating to that virtual host will be
# logged here.  If you *do* define an error logfile for a <VirtualHost>
# container, that host's errors will be logged there and not here.
ErrorLog ${APACHE_LOG_DIR}/error.log
# LogLevel: Control the severity of messages logged to the error_log.
# error, crit, alert, emerg.
$ cat /etc/apache2/apache2.conf | grep APACHE_LOG_DIR
ErrorLog ${APACHE_LOG_DIR}/error.log
$ cat /etc/apache2/envvars | grep APACHE_LOG_DIR
export APACHE_LOG_DIR=/var/log/apache2$SUFFIX
$ ls /var/log/apache2/
access.log  error.log  other_vhosts_access.log

結果

きちんと測定したわけではありませんが、体感速度は倍以上UPしました。
最近は SLC の USBメモリは出回っていませんが、I/O を microSD(システム)と USB(SQLite)で分けるだけでも効果があるはずなので一考の価値ありではないでしょうか。