Błąd krytyczny: Nie można otworzyć i zablokować tabel uprawnień: Mechanizm przechowywania tabel dla „użytkownika” nie ma tej opcji

15

Ten komunikat o błędzie pojawia się, gdy używam Ubuntu 16.04 i najnowszego mysql 5.7.19-0ubuntu0.16.04.1 na obrazie Docker.

Co można zrobić, aby to naprawić?

Aby odtworzyć błąd

  1. Uzyskaj Dockerfile:

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

    (dostępny również tutaj )

  2. Zbuduj i uruchom:

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

    wyświetliłby się następujący dziennik błędów:

    2017-08-26T11: 48: 45.398445Z 1 [Ostrzeżenie] root @ localhost jest tworzony z pustym hasłem! Rozważ wyłączenie opcji --initialize-niepewne.

    Właśnie tego chcieliśmy: mysql bez ustawionego hasła roota.

  3. W przeszłości (ubuntu 14.04 / mysql 5.5) service mysql startbyło możliwe. Teraz, jeśli spróbujesz tego, nie powiedzie się

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

    i /var/log/mysql/error.logzawiera wiersz:

    2017-08-26T11: 59: 57.680618Z 0 [BŁĄD] Błąd krytyczny: Nie można otworzyć i zablokować tabel uprawnień: Mechanizm przechowywania tabel dla „użytkownika” nie ma tej opcji


dziennik kompilacji (dla kompletu 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

dziwna kontynuacja

Po eksperymentach opisanych w mojej próbie odpowiedzi utworzyłem skrypt powłoki, który wykonuje polecenie

select count(*)

zapytanie do każdej tabeli w przestrzeni mysql trzy razy z rzędu (ponieważ eksperymenty pokazują, że w niektórych tabelach zapytanie nie powiedzie się dokładnie dwa razy :-().

Następnie

mysql_upgrade   

i

service mysql restart

jest próbowany. W Dockerfileskrypcie jest udostępniany za pośrednictwem

COPY mysqltest.sh .

Próby z tym skryptem dają dziwne / szalone wyniki.

  1. Ponieważ Docker environmentstart wciąż się nie udaje

    [BŁĄD] Błąd krytyczny: Nie można otworzyć i zablokować tabel uprawnień: Mechanizm przechowywania tabel dla „użytkownika” nie ma tej opcji

  2. Uruchamianie skryptu

    sh mysqltest.sh root
    

    w docker environmentprowadzi do

    2017-08-27T09: 12: 47.021528Z 12 [BŁĄD] / usr / sbin / mysqld: Tabela „./mysql/db” jest oznaczony jako uszkodzony i powinien zostać naprawiony
    2017-08-27T09: 12: 47.050141Z 12 [BŁĄD ] Nie można naprawić tabeli: mysql.db
    2017-08-27T09: 12: 47.055925Z 13 [BŁĄD] / usr / sbin / mysqld: Tabela „./mysql/db” jest oznaczona jako
    rozbita i powinna zostać naprawiona 2017-08 -27T09: 12: 47.407700Z 54 [ERROR] / usr / sbin / mysqld: Table './mysql/proc' jest oznaczony jako rozbity i powinien zostać naprawiony
    2017-08-27T09: 12: 47.433516Z 54 [ERROR] Couldn ' Tabela naprawy: mysql.proc
    2017-08-27T09: 12: 47.440695Z 55 [BŁĄD] / usr / sbin / mysqld: Tabela „./mysql/proc” jest oznaczona jako
    rozbita i powinna zostać naprawiona 2017-08-27T09: 12: 47.769485Z 81 [BŁĄD] / usr / sbin / mysqld: Table './mysql/tables_priv'jest oznaczony jako rozbity i powinien zostać naprawiony
    2017-08-27T09: 12: 47.792061Z 81 [BŁĄD] Nie można naprawić tabeli: mysql.tables_priv
    2017-08-27T09: 12: 47.798472Z 82 [BŁĄD] / usr / sbin / mysqld: Table './mysql/ table_priv ”jest oznaczony jako rozbity i powinien zostać naprawiony
    2017-08-27T09: 12: 47.893741Z 99 [ERROR] / usr / sbin / mysqld: Table './mysql/user' jest oznaczony jako rozbity i powinien zostać naprawiony
    2017-08 -27T09: 12: 47.914288Z 99 [BŁĄD] Nie można naprawić tabeli: mysql.user
    2017-08-27T09: 12: 47.920459Z 100 [BŁĄD] / usr / sbin / mysqld: Tabela „./mysql/user” to oznaczony jako rozbity i powinien zostać naprawiony

Co się tutaj dzieje, aby spowodować to dziwne zachowanie?

Wolfgang Fahl
źródło
1
mysqld --skip-grant-tables --skip-networking wydaje się działać
Wolfgang Fahl
mkdir / var / run / mysqld; może być również potrzebny chown mysql / var / run / mysqld.
Wolfgang Fahl
1
--skip-networking wyłączy wszelkie połączenia TCP / IP, które możesz chcieć nawiązać z serwerem, więc czasami jest to złe. mariadb.com/kb/en/server-system-variables/#skip_networking
Darko Maksimovic
@DarkoMaksimovic zobacz zaakceptowaną odpowiedź na ustawienie własności jako rozwiązanie.
Wolfgang Fahl
W rzeczywistości już tego próbowałem i nic to nie zmieniło w moim przypadku (MySQL 5.7 na MacOS, Docker 2.1.0.5). Tylko --skip-grant-tables pomogło uruchomić serwer, chociaż ktoś w tym wątku narzekał na dalsze wybory, ale zobaczę, kiedy mi się to przydarzy.
Darko Maksimovic

Odpowiedzi:

31

Wpadłem dzisiaj na ten sam problem. Korzystam z usługi MySQL podczas kompilacji dokera w celu przeprowadzenia testów jednostkowych, a aktualizacja do MySQL CE 5.7.19 z MariaDB przerwała kompilację. To, co rozwiązało problem, działało za chown -R mysql:mysql /var/lib/mysql /var/run/mysqldkażdym razem przed uruchomieniem usługi mysql.

Mój plik Docker wygląda teraz tak:

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

Mam nadzieję że to pomoże.

Tibor Gyuris
źródło
2
Mam ten sam problem. Miałem działającą dwustopniową kompilację, a „macierzysty” plik Dockerfile już uruchamia to chmodpolecenie. Kompilacja kończy się powodzeniem, gdy uruchamiam ją na zdalnym serwerze Ubuntu, ale kończy się niepowodzeniem, gdy uruchamiam ją na moim komputerze lokalnym (OS X). Dodanie chmodpolecenia do potomnego Dockerfile rozwiązało problem. Dziwne .
senderle
2
Dziękuję Ci! Wiedziałem, że ktoś tam musi mieć podobny przypadek użycia jak mój.
zagrali
2
@senderle właśnie znalazł ten wątek. „Buduj raz, wdrażaj gdziekolwiek”
duhaime,
9

Obejście

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

Opis problemu

Podstawowy problem wskazany przez aalexgabi wynika z implementacji standardów OverlayFS POSIX :

open (2): OverlayFS implementuje tylko podzbiór standardów POSIX. Może to spowodować, że niektóre operacje OverlayFS złamią standardy POSIX. Jedną z takich operacji jest operacja kopiowania. Załóżmy, że aplikacja dzwoni, fd1=open("foo", O_RDONLY)a następnie fd2=open("foo", O_RDWR). W takim przypadku aplikacja oczekuje, że fd1 i fd2 będą odnosić się do tego samego pliku. Jednak z powodu operacji kopiowania, która ma miejsce po drugim wywołaniu do open(2), deskryptory odnoszą się do różnych plików. Fd1 nadal odwołuje się do pliku na obrazie (katalog dolny), a fd2 odwołuje się do pliku w kontenerze (katalog górny). Obejściem tego problemu jest dotknięcie plików, które powoduje operację kopiowania. Wszystkie kolejne open(2)operacje, niezależnie od trybu dostępu tylko do odczytu lub odczytu i zapisu, będą odnosić się do pliku w kontenerze (katalog górny).

Odniesienie:

Murmel
źródło
1
To okropne wieści. Zastanawiam się, dlaczego doker nie jest naprawiony.
Wolfgang Fahl
2
Szczerze? Ja też nie! Mam na myśli, że musi to wpływać na wiele aplikacji, ponieważ jest to tak naprawdę podstawowa operacja na pliku. Oczywiście problem występuje tylko pod pewnymi warunkami, ale nie są tak daleko ...
Murmel,
8

Potwierdziłem błąd w overlayfs (overlay2), który jest domyślny w Docker na Mac. Błąd występuje podczas uruchamiania mysql na obrazie, po utworzeniu obrazu za pomocą 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

Przejście na „aufs” rozwiązało problem. (W Docker dla komputerów Mac „daemon.json” można edytować, wybierając menu „Preferencje ...”, a następnie zakładkę „Daemon” i zakładkę „Zaawansowane”).

/etc/docker/daemon.json:

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

Ref:

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

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

Tsuneo Yoshioka
źródło
1
To rozwiązało mój problem w Ubuntu 16:04. Skonfigurowałem wcześniej sterownik magazynu nakładki2 w oknie dokowanym. Dzięki.
Havok,
1
Zapobiegło to ponownemu uruchomieniu
dokera
2

Oto odpowiedź, której jeszcze tu nie widzę.

Dodaj to do pliku dokera: VOLUME /var/lib/mysql

Spowoduje to, że folder / var / lib / mysql będzie używał rodzimego systemu plików zamiast overlayFS. To omija ten problem.

Jest to rozwiązanie, którego używa oficjalny obraz dokera mysql, aby sobie z tym poradzić, jak widać tutaj: https://github.com/docker-library/mysql/blob/9d1f62552b5dcf25d3102f14eb82b579ce9f4a26/5.7/Dockerfile

Paul Dejean
źródło
1

To może jeszcze nie być rozwiązaniem. W każdym razie może to wskazywać innym na „właściwą” odpowiedź

Poniższy dziennik sesji bash Dockera pokazuje sekwencję kroków, które prowadzą do dziwnych błędów i ostatecznie są w stanie poprawnie uruchomić demona mysql w środowisku dokera.

Próba uruchomienia demona w tej sesji kończy się niepowodzeniem dwa razy - raz z powodu tabeli mysql.user i raz z powodu tabeli mysql.db. Uruchamianie demona mysql z opcją --skip-grant-tables działa, ale występują również problemy z prostym wyborem * z poleceń w tych tabelach.

Dziwnie robię dwa proste zapytania:

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

a następnie zabicie demona, aby poprawnie go uruchomić

service mysql start

wydaje się działać. Spróbuję teraz zautomatyzować to rozwiązanie. Wciąż szukam „właściwego” rozwiązania problemu i mam pewne wskazówki, co jest przyczyną tego dziwnego zachowania.

Plik Docker

#*********************************************************************
#
# Dockerfile for /server/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

dziennik kompilacji

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

dziennik sesji 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 ]
Wolfgang Fahl
źródło
Spójrz na oryginalny plik doker github.com/docker-library/mysql/blob/... i entrypoint.sh github.com/docker-library/mysql/blob/... . Dadzą ci wyobrażenie, co należy zrobić.
Tarun Lalwani
Dziękuję za podpowiedź. Moje dalsze eksperymenty pokazują, że seria wydań 5.7.x zachowuje się inaczej w zależności od x. Wydaje się, że do 5.7.14 było to prostsze. Severalnines.com/blog/... podejście działa w moim środowisku Linux. W moim środowisku Mac OS sprawy są trudniejsze.
Wolfgang Fahl