シナプス技術者ブログ

シナプスの技術者公式ブログ。インターネットで、鹿児島の毎日を笑顔にします。

TiDBでWordPressを動かしてみた

こんにちは、技術部ネットワーク課の上曽山です。

近年注目を集めているNewSQLの中で特に人気がある(らしい)「TiDB」とはどんなものなのか、興味があったので動かしてみました。
ただデータベースを立ち上げるだけでは面白くないと思いTiDBでWordPressを動かしてみたところ、少し躓く場面があったのでここにまとめました。

TiDBについて

開発元であるPingCAP株式会社のサイトにドキュメントが用意されています。
詳しくは、こちらをご覧ください。 docs.pingcap.com


サーバー環境

これが主なインストール済みパッケージです。

バージョン
OS rocky-release-9.2-1.6.el9
httpd httpd-2.4.53-11.el9_2.5
php php-8.0.27-1.el9_1
mysql mysql-8.0.32-1.el9_2


下準備

TiDBのコンポーネントに割り当てるプライベートIPアドレスで 通信が出来るよう、loopbackインターフェースの設定を変更します。

  • loopbackインターフェースを操作出来るようにする
$ sudo nmcli device connect lo
  • loopbackインターフェースにIPアドレスを設定
$ sudo nmcli connection modify lo +ipv4.addresses "10.0.1.1"
  • 設定を反映
$ sudo nmcli connection up lo


また、sudoコマンドをパスワード無しで実行出来るようにしておかないとデプロイに失敗するため設定を追加します。
ここで使用しているユーザー名はダミーです。

$ echo "hoge ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/hoge
hoge ALL=(ALL) NOPASSWD:ALL


TiDBのセットアップ

公式ドキュメントの「単一マシン上で本番デプロイメントをシミュレートする」手順に従い、TiDBのセットアップを行いました。

以下はドキュメントに書いていない手順ですが、TABキーでコマンドが補完出来ると便利なのでオススメです。(要bash-completion)

  • bash-completion用スクリプト作成
$ tiup completion bash | sudo tee /etc/bash_completion.d/tiup
(以下、省略)
  • 設定反映
$ source /etc/bash_completion.d/tiup

「tiup」まで入力してTABを2回押すと、この通り。

$ tiup
clean       (Clean the data of instantiated components)
completion  (Generate the autocompletion script for the specified shell)
env         (Show the list of system environment variable that related to TiUP)
help        (Help about any command)
history     (Display the historical execution record of TiUP, displays 100 lines by default)
install     (Install a specific version of a component)
list        (List the available TiDB components or versions)
mirror      (Manage a repository mirror for TiUP components)
status      (List the status of instantiated components)
telemetry   (Controls things about telemetry)
uninstall   (Uninstall components or versions of a component)
update      (Update tiup components to the latest version)


WordPress用データベース作成

TiDBのセットアップが終わったらWordPress用のデータベースとユーザーを作成します。
データベース/ユーザーの作成は、MySQLと同じコマンドで行えます。

  • TiDBにログイン
$ mysql -h 10.0.1.1 -P 4000 -u root
  • WordPress用データベースの作成
mysql> CREATE DATABASE testdb;
  • WordPress用ユーザーの作成
mysql> CREATE USER 'tidbtest'@'localhost' IDENTIFIED BY '**********';
  • ユーザー権限の設定
mysql> GRANT ALL ON testdb.* TO 'tidbtest'@'localhost';
  • 権限反映
mysql> FLUSH PRIVILEGES;
  • TiDBからログアウト
mysql> quit


WordPressのセットアップ

WordPressのファイルはサーバーにアップロード済みです。

$ ls -l /var/www/html/wordpress/
total 228
-rw-r--r--  1 apache apache   405 Feb  6  2020 index.php
-rw-r--r--  1 apache apache 19915 Aug  9 06:14 license.txt
-rw-r--r--  1 apache apache  7399 Aug  9 06:14 readme.html
-rw-r--r--  1 apache apache  7211 May 13 06:35 wp-activate.php
drwxr-xr-x  9 apache apache  4096 Aug  9 06:00 wp-admin
-rw-r--r--  1 apache apache   351 Feb  6  2020 wp-blog-header.php
-rw-r--r--  1 apache apache  2323 Jun 14 23:11 wp-comments-post.php
-rw-r--r--  1 apache apache  3013 Aug  9 06:14 wp-config-sample.php
drwxr-xr-x  5 apache apache    69 Aug  9 06:15 wp-content
-rw-r--r--  1 apache apache  5638 May 31 03:48 wp-cron.php
drwxr-xr-x 27 apache apache 12288 Aug  9 06:15 wp-includes
-rw-r--r--  1 apache apache  2502 Nov 27  2022 wp-links-opml.php
-rw-r--r--  1 apache apache  3927 Jul 16 21:16 wp-load.php
-rw-r--r--  1 apache apache 49441 Jul 17 22:18 wp-login.php
-rw-r--r--  1 apache apache  8537 Jun 22 23:36 wp-mail.php
-rw-r--r--  1 apache apache 25602 Jul 25 15:35 wp-settings.php
-rw-r--r--  1 apache apache 34385 Jun 20 03:27 wp-signup.php
-rw-r--r--  1 apache apache  4885 Jun 22 23:36 wp-trackback.php
-rw-r--r--  1 apache apache  3236 Jun 14 23:11 xmlrpc.php


ブラウザでアクセスしてインストールを開始します。


データベースの情報を入力して先に進めます。
ポート番号「4000」を指定するためにホスト名はIPアドレスで入力しています。


データベースと通信出来る事が確認出来たら「インストール実行」します。


引き続き必要事項を入力して「WordPressをインストール」します。


すると、エラーが発生しました。

テーブル作成時にTiDBが対応していないCollationを使おうとした事がエラーの原因でした。

$ mysql -h 10.0.1.1 -P 4000 -u root -e "SHOW COLLATION;"
+--------------------+---------+------+---------+----------+---------+
| Collation          | Charset | Id   | Default | Compiled | Sortlen |
+--------------------+---------+------+---------+----------+---------+
| ascii_bin          | ascii   |   65 | Yes     | Yes      |       1 |
| binary             | binary  |   63 | Yes     | Yes      |       1 |
| gbk_bin            | gbk     |   87 |         | Yes      |       1 |
| gbk_chinese_ci     | gbk     |   28 | Yes     | Yes      |       1 |
| latin1_bin         | latin1  |   47 | Yes     | Yes      |       1 |
| utf8_bin           | utf8    |   83 | Yes     | Yes      |       1 |
| utf8_general_ci    | utf8    |   33 |         | Yes      |       1 |
| utf8_unicode_ci    | utf8    |  192 |         | Yes      |       1 |
| utf8mb4_bin        | utf8mb4 |   46 | Yes     | Yes      |       1 |
| utf8mb4_general_ci | utf8mb4 |   45 |         | Yes      |       1 |
| utf8mb4_unicode_ci | utf8mb4 |  224 |         | Yes      |       1 |
+--------------------+---------+------+---------+----------+---------+


WordPress側で使用するCollationを決めているようなので、設定を行うファイルを特定してエラーが出ないようにします。

  • 「utf8mb4_unicode_520_ci」を含むファイルを検索
[staff@dev9 ~]$ grep -lrs "utf8mb4_unicode_520_ci" /var/www/html/wordpress/
/var/www/html/wordpress/wp-includes/class-wpdb.php
  • ファイルの内容を確認
$ cat -n /var/www/html/wordpress/wp-includes/class-wpdb.php | grep -C3 "utf8mb4_unicode_520_ci"
   904
   905                  // _unicode_520_ is a better collation, we should use that when it's available.
   906                  if ( $this->has_cap( 'utf8mb4_520' ) && 'utf8mb4_unicode_ci' === $collate ) {
   907                          $collate = 'utf8mb4_unicode_520_ci';
   908                  }
   909
   910                  return compact( 'charset', 'collate' );
  • 906行目~908行目をコメントアウト
sudo sed -i.bak -e '906,908 s|^|//|' /var/www/html/wordpress/wp-includes/class-wpdb.php
  • 変更箇所確認
                }

                // _unicode_520_ is a better collation, we should use that when it's available.
-               if ( $this->has_cap( 'utf8mb4_520' ) && 'utf8mb4_unicode_ci' === $collate ) {
-                       $collate = 'utf8mb4_unicode_520_ci';
-               }
+//             if ( $this->has_cap( 'utf8mb4_520' ) && 'utf8mb4_unicode_ci' === $collate ) {
+//                     $collate = 'utf8mb4_unicode_520_ci';
+//             }

                return compact( 'charset', 'collate' );
        }


ファイルを修正したら、ブラウザに戻って画面をリロードします。
リロードしても画面の表示は変わりませんが、しばらく待てばインストールは完了(するはず)です。


WordPressの動作確認

それでは管理画面にログインして投稿テストを行いたいと思います。

と、その前に、今回はhttpdをデフォルト設定で動かしているため、URLのリダイレクトが機能しない(.htaccessの内容が反映されない)可能性があります。
まずはパーマリンクの設定を「基本」に変更します。


次に「投稿一覧」を開きます。
この画面の時点で違和感がありますけど、とりあえず進めます。


投稿を「新規作成」して「公開」します。


「投稿を表示する」で正常にページが表示される事を確認します。


再びダッシュボードに戻って投稿一覧を確認します。
先程はスルーしましたが、投稿一覧に何も表示されていません。
投稿数のカウントは増えているし、先ほどページの表示も確認したので、投稿内容が消えた訳ではないはずです。


もろもろ確認した結果、TiDBのログにエラーが出力されている事が分かりました。

$ sudo grep "WARN.*wp_posts" /tidb-deploy/tidb-4000/log/tidb.log | tail -1
(省略)[error="[expression:1235]function SQL_CALC_FOUND_ROWS has only noop implementation in tidb now, use tidb_enable_noop_functions to enable these functions"](省略)


投稿一覧を表示する際にSQL_CALC_FOUND_ROWS関数を使うようですが、TiDBのデフォルト設定では関数が実行出来ないためパラメーターを変更します。

  • TiDBのGLOBAL変数を確認
$ mysql -h 10.0.1.1 -P 4000 -u root -e "SHOW GLOBAL VARIABLES LIKE 'tidb_enable_noop_functions'"
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| tidb_enable_noop_functions | OFF   |
+----------------------------+-------+
  • TiDBのGLOBAL変数を変更
$ mysql -h 10.0.1.1 -P 4000 -u root -e "SET GLOBAL tidb_enable_noop_functions=1"
  • 「tidb_enable_noop_functions」が「ON」になっている事を確認
$ mysql -h 10.0.1.1 -P 4000 -u root -e "SHOW GLOBAL VARIABLES LIKE 'tidb_enable_noop_functions'"
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| tidb_enable_noop_functions | ON    |
+----------------------------+-------+


改めて投稿ページを表示すると、投稿一覧が表示されるようになっていました。

この後、TiDBのログを確認しながら、いくつかメニューを開いて操作してみましたが、エラーは出力されなかったので他の部分は問題なさそうです。


所感

TiDBに触れ、一部ではありますがMySQLとの相違点について確認する事が出来たのは良い経験になりました。
とはいえTiDBの特徴である分散アーキテクチャの部分は試していないので、次は本番に近い環境で試してみたいと思います。