致命错误:无法打开和锁定特权表:“用户”的表存储引擎没有此选项

致命错误:无法打开和锁定特权表:“用户”的表存储引擎没有此选项

当我在 Docker 镜像中使用 ubuntu 16.04 和最新的 mysql 5.7.19-0ubuntu0.16.04.1 时出现此错误消息。

怎样才能修复此问题?

重现错误

  1. 获取Dockerfile

    FROM ubuntu:16.04
    
    RUN apt update
    RUN DEBIAN_FRONTEND=noninteractive apt install -y mysql-server
    

    (也提供这里

  2. 构建并运行:

    docker build -t mysqlfail . 
    docker run -it mysqlfail tail -1 /var/log/mysql/error.log
    

    将显示以下错误日志:

    2017-08-26T11:48:45.398445Z 1 [警告] root@localhost 使用空密码创建!请考虑关闭 --initialize-insecure 选项。

    这正是我们想要的:一个尚未设置 root 密码的 mysql。

  3. 在过去 (ubuntu 14.04 / mysql 5.5)service mysql start是可能的。现在如果你尝试这个,它会失败

    docker run -it mysqlfail service mysql start
     * Starting MySQL database server mysqld    
      No directory, logging in with HOME=/  
                                                                            [fail]
    

    /var/log/mysql/error.log包含一行:

    2017-08-26T11:59:57.680618Z 0 [错误] 致命错误:无法打开和锁定特权表:“用户”的表存储引擎没有此选项


构建日志(完整Dockerfile

Sending build context to Docker daemon   2.56kB
Step 1/4 : FROM ubuntu:16.04
 ---> ebcd9d4fca80
...
Step 4/4 : RUN service mysql start
 ---> Running in 5b899739d90d
 * Starting MySQL database server mysqld
   ...fail!
The command '/bin/sh -c service mysql start' returned a non-zero code: 1

奇怪的延续

经过如下实验我的回答尝试,我创建了一个 shell 脚本,它执行

select count(*)

对mysql空间中的每个表连续进行三次查询(因为实验表明,在某些表上查询将会失败两次:-())。

然后

mysql_upgrade   

service mysql restart

尝试。在Dockerfile脚本中,可以通过

COPY mysqltest.sh .

使用该脚本的试验产生了奇怪/疯狂的结果。

  1. 为了Docker environment启动仍然失败

    [错误]致命错误:无法打开和锁定权限表:“用户”的表存储引擎没有此选项

  2. 运行脚本

    sh mysqltest.sh root
    

    在里面docker environment导致

    2017-08-27T09:12:47.021528Z 12 [错误] /usr/sbin/mysqld:表'。/mysql/db'被标记为崩溃,应进行修复
    2017-08-27T09:12:47.050141Z 12 [错误]无法修复表:mysql.db
    2017-08-27T09:12:47.055925Z 13 [错误] /usr/sbin/mysqld:表'。/mysql/db'被标记为崩溃,应进行修复
    2017-08-27T09:12:47.407700Z 54 [错误] /usr/sbin/mysqld:表'。/mysql/proc'被标记为崩溃,应进行修复
    2017-08-27T09:12:47.433516Z 54 [错误] 无法修复表:mysql.proc
    2017-08-27T09:12:47.440695Z 55 [错误] /usr/sbin/mysqld:表'./mysql/proc'被标记为崩溃,应修复
    2017-08-27T09:12:47.769485Z 81 [错误] /usr/sbin/mysqld:表'./mysql/tables_priv'被标记为崩溃,应修复
    2017-08-27T09:12:47.792061Z 81 [错误] 无法修复表:mysql.tables_priv
    2017-08-27T09:12:47.798472Z 82 [错误] /usr/sbin/mysqld:表'。/mysql/tables_priv'被标记为崩溃,应进行修复
    2017-08-27T09:12:47.893741Z 99 [错误] /usr/sbin/mysqld:表'。/mysql/user'被标记为崩溃,应进行修复
    2017-08-27T09:12:47.914288Z 99 [错误]无法修复表:mysql.user
    2017-08-27T09:12:47.920459Z 100 [错误] /usr/sbin/mysqld:表'。/mysql/user'被标记为崩溃,应进行修复

这里发生了什么,导致了这种奇怪的行为?

答案1

今天遇到了同样的问题。我在 docker 构建期间运行 MySQL 服务进行单元测试,从 MariaDB 升级到 MySQL CE 5.7.19 破坏了构建。对我来说解决问题的方法是chown -R mysql:mysql /var/lib/mysql /var/run/mysqld每次在启动 mysql 服务之前运行。

所以我的 Dockerfile 现在看起来像这样:

RUN chown -R mysql:mysql /var/lib/mysql /var/run/mysqld && \
    service mysql start && \
    mvn -q verify site

希望这可以帮助。

答案2

解决方法

find /var/lib/mysql -type f -exec touch {} \; && service mysql start

问题描述

潜在的问题如下亚历克斯加比是由于OverlayFS 的 POSIX 标准的实现

open(2):OverlayFS 仅实现了 POSIX 标准的子集。这可能导致某些 OverlayFS 操作违反 POSIX 标准。其中一个操作是复制操作。假设您的应用程序调用fd1=open("foo", O_RDONLY)然后调用fd2=open("foo", O_RDWR)。在这种情况下,您的应用程序希望 fd1 和 fd2 引用同一个文件。但是,由于在第二次调用之后发生了复制操作open(2,因此描述符引用不同的文件。fd1 继续引用映像中的文件 (lowerdir),而 fd2 引用容器中的文件 (upperdir)。解决此问题的方法是触摸导致复制操作发生的文件。所有后续open(2)操作,无论是只读还是读写访问模式,都将引用容器中的文件 (upperdir)。

参考:

答案3

我确认错误发生在 Docker for Mac 默认的 overlayfs (overlay2) 上。在使用 mysql 创建镜像后,在镜像上启动 mysql 时发生此错误。

2017-11-15T06:44:22.141481Z 0 [ERROR] Fatal error: Can't open and lock privilege tables: Table storage engine for 'user' doesn't have this option

切换到“aufs”解决了这个问题。(在 Docker for Mac 上,可以通过选择“首选项...”菜单,选择“守护进程”选项卡,然后选择“高级”选项卡来编辑“daemon.json”。)

/etc/docker/daemon.json:

{
  "storage-driver" : "aufs",
  "debug" : true,
  "experimental" : true
}

参考:

https://github.com/moby/moby/issues/35503

https://qiita.com/Hige-Moja/items/7b1208f16997e2aa9028

答案4

这可能还不是解决方案。无论如何,它可能会为其他人指明一个“正确”的答案

下面的 docker bash 会话日志展示了导致奇怪错误的一系列步骤,最终能够在 docker 环境中正确启动 mysql 守护进程。

在此会话中尝试启动守护进程失败两次 - 一次是由于 mysql.user 表,一次是由于 mysql.db 表。使用 --skip-grant-tables 运行 mysql 守护进程可以正常工作,但对这些表执行简单的 select * from 命令也会出现问题。

奇怪的是做了两个简单的查询:

select host,user from mysql.user;
select user from mysql.db

然后终止守护进程以正确启动它

service mysql start

似乎有效。我现在将尝试将其自动化作为一种​​解决方法。我仍在寻找问题的“正确”解决方案,并寻找导致这种奇怪行为的原因。

Dockerfile

#*********************************************************************
#
# Dockerfile for https://serverfault.com/questions/870568/2017-08-26t113924-509100z-0-error-fatal-error-cant-open-and-lock-privilege
#
#*********************************************************************

# Ubuntu image
FROM ubuntu:16.04

# 
# Maintained by Wolfgang Fahl / BITPlan GmbH http://www.bitplan.com
# 
MAINTAINER Wolfgang Fahl [email protected]

RUN \
 export DEBIAN_FRONTEND=noninteractive;apt-get update -y && apt-get install -y \
        vim \
    mysql-server 

RUN mkdir /var/run/mysqld;chown mysql /var/run/mysqld
WORKDIR /var/log/mysql

构建日志

docker build .

Sending build context to Docker daemon  8.704kB
Step 1/5 : FROM ubuntu:16.04
 ---> ebcd9d4fca80
Step 2/5 : MAINTAINER Wolfgang Fahl [email protected]
 ---> Using cache
 ---> b84df9d5de50
Step 3/5 : RUN export DEBIAN_FRONTEND=noninteractive;apt-get update -y && apt-get install -y         vim    mysql-server
 ---> Using cache
 ---> b51bd2bb172c
Step 4/5 : RUN mkdir /var/run/mysqld;chown mysql /var/run/mysqld
 ---> Using cache
 ---> 5b7455fede6b
Step 5/5 : WORKDIR /var/log/mysql
 ---> c4c333e811ab
Removing intermediate container cfc49e460c96
Successfully built c4c333e811ab

bash 会话日志

docker run -it c4c333e811ab

root@607fa9fe8d98:/var/log/mysql# service mysql start
 * Starting MySQL database server mysqld                                                             No directory, logging in with HOME=/
                                                                                              [fail]
root@607fa9fe8d98:/var/log/mysql# grep ERROR error.log 
2017-08-27T07:56:21.377919Z 0 [ERROR] Fatal error: Can't open and lock privilege tables: Table storage engine for 'user' doesn't have this option
2017-08-27T07:56:21.378149Z 0 [ERROR] Aborting
mysqld_safe --skip-grant-tables&sleep 2;mysql -u root -p=""
select * from mysql.user;
ERROR 1031 (HY000): Table storage engine for 'user' doesn't have this option
select host,user from mysql.user;
+-----------+------------------+
| host      | user             |
+-----------+------------------+
| localhost | debian-sys-maint |
| localhost | mysql.session    |
| localhost | mysql.sys        |
| localhost | root             |
+-----------+------------------+
4 rows in set (0.00 sec)
show variables like "%locking%";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| skip_external_locking | ON    |
+-----------------------+-------+
1 row in set (0.01 sec)
root@607fa9fe8d98:/var/log/mysql# pgrep -fla mysql
721 /bin/sh /usr/bin/mysqld_safe --skip-grant-tables
1083 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=mysql --skip-grant-tables --log-error=/var/log/mysql/error.log --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=3306 --log-syslog=1 --log-syslog-facility=daemon --log-syslog-tag=
pkill -f mysql
echo "" > error.log
service mysql start
 * Starting MySQL database server mysqld                                                             No directory, logging in with HOME=/.      [fail]
grep ERROR error.log 
2017-08-27T08:03:12.918047Z 0 [ERROR] Fatal error: Can't open and lock privilege tables: Table storage engine for 'db' doesn't have this option
2017-08-27T08:03:12.918278Z 0 [ERROR] Aborting
mysqld_safe --skip-grant-tables&sleep 2;mysql -u root -p=""
select * from mysql.db;
ERROR 1031 (HY000): Table storage engine for 'db' doesn't have this option
select user from mysql.db;
+---------------+
| user          |
+---------------+
| mysql.session |
| mysql.sys     |
+---------------+
2 rows in set (0.00 sec)
echo "" > error.log
root@607fa9fe8d98:/var/log/mysql# service mysql start
 * Starting MySQL database server mysqld      [ OK ]

相关内容