Debian系Linuxでdatadirを変更したらmysqlが起動しない

概要
---------------
Ubuntuでdatadirをデフォルトから変更してmysqlを起動しようとすると起動しないという問題が発生して解決したのでその調査ログ

問題の再現手順
---------------
1) datadirをデフォルトの/var/lib/mysqlから変更する

```/etc/my.cnf
[mysqld]
#
# * Basic Settings
#
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
- datadir         = /var/lib/mysql
+ datadir         = /export/mysql
tmpdir          = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
```

2) mysqlを再起動しようとすると起動しない

```shell-session
root@twain:/export/Windows# /etc/init.d/mysql restart
 * Starting MySQL database server mysqld                                                                             [ Fail ]
```

原因調査
---------------
まずmysqlのエラーログを調べてみる

```/var/log/mysql/error.log
141231 17:05:26 [Warning] Using unique option prefix myisam-recover instead of myisam-recover-options is deprecated and will
 be removed in a future release. Please use the full name instead.
141231 17:05:26 [Note] Plugin 'FEDERATED' is disabled.
^G/usr/sbin/mysqld: Can't find file: './mysql/plugin.frm' (errno: 13)
141231 17:05:26 [ERROR] Can't open the mysql.plugin table. Please run mysql_upgrade to create it.
141231 17:05:26 InnoDB: The InnoDB memory heap is disabled
141231 17:05:26 InnoDB: Mutexes and rw_locks use GCC atomic builtins
141231 17:05:26 InnoDB: Compressed tables use zlib 1.2.8
141231 17:05:26 InnoDB: Using Linux native AIO
141231 17:05:26 InnoDB: Initializing buffer pool, size = 128.0M
141231 17:05:26 InnoDB: Completed initialization of buffer pool
141231 17:05:26  InnoDB: Operating system error number 13 in a file operation.
InnoDB: The error means mysqld does not have the access rights to
InnoDB: the directory.
InnoDB: File name ./ibdata1
InnoDB: File operation call: 'open'.
InnoDB: Cannot continue operation.
```

なぜかibdata1のファイルオープンに失敗しているように見えるが、パーミッションもファイルオーナーも特に問題がない・・・

次にdmesgを見てみる

```dmesg
[1266962.296804] type=1400 audit(1420014191.955:60): apparmor="DENIED" operation="mknod" profile="/usr/sbin/mysqld" name="/export/mysql/twain.lower-test" pid=12192 comm="mysqld" requested_mask="c" denied_mask="c" fsuid=0 ouid=0
[1266962.296941] type=1400 audit(1420014191.955:61): apparmor="DENIED" operation="mknod" profile="/usr/sbin/mysqld" name="/export/mysql/twain.lower-test" pid=12192 comm="mysqld" requested_mask="c" denied_mask="c" fsuid=0 ouid=0
[1266962.302459] type=1400 audit(1420014191.959:62): apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/export/mysql/mysql/plugin.frm" pid=12192 comm="mysqld" requested_mask="r" denied_mask="r" fsuid=102 ouid=102
[1266962.384859] type=1400 audit(1420014192.043:63): apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/export/mysql/ibdata1" pid=12192 comm="mysqld" requested_mask="rw" denied_mask="rw" fsuid=102 ouid=102
```

[apparmor](https://ja.opensuse.org/AppArmor)というSELinuxのようなアクセス制御機構によってアクセス拒否されているらしい

対策
---------------
AppArmorの設定を変更すれば良さそうだ

AppArmorのmysql設定ファイル(/etc/apparmor.d/usr.sbin.mysqld)を修正する

```/etc/apparmor.d/usr.sbin.mysqld
/usr/sbin/mysqld {
  #include <abstractions/base>
  #include <abstractions/nameservice>
  #include <abstractions/user-tmp>
  #include <abstractions/mysql>
  #include <abstractions/winbind>

  capability dac_override,
  capability sys_resource,
  capability setgid,
  capability setuid,

  network tcp,

  /etc/hosts.allow r,
  /etc/hosts.deny r,

  /etc/mysql/*.pem r,
  /etc/mysql/conf.d/ r,
  /etc/mysql/conf.d/* r,
  /etc/mysql/*.cnf r,
  /usr/lib/mysql/plugin/ r,
  /usr/lib/mysql/plugin/*.so* mr,
  /usr/sbin/mysqld mr,
  /usr/share/mysql/** r,
  /var/log/mysql.log rw,
  /var/log/mysql.err rw,
  /var/lib/mysql/ r,
  /var/lib/mysql/** rwk,
+  /export/mysql/ r,
+  /export/mysql/** rwk,
  /var/log/mysql/ r,
  /var/log/mysql/* rw,
  /var/run/mysqld/mysqld.pid rw,
  /var/run/mysqld/mysqld.sock w,
  /run/mysqld/mysqld.pid rw,
  /run/mysqld/mysqld.sock w,

  /sys/devices/system/cpu/ r,

  # Site-specific additions and overrides. See local/README for details.
  #include <local/usr.sbin.mysqld>
}
```

設定を反映するためにapparmorをリロードする

```shell-session
root@twain:/export/Windows# invoke-rc.d apparmor reload
```

あとは普通にmysqlを起動すれば良い

```shell-session
root@twain:/export/Windows# /etc/init.d/mysql restart
 * Starting MySQL database server mysqld                                                                             [ OK ]
```