LoginSignup
3
4

More than 5 years have passed since last update.

「Dockerを使ってMySQLのソースコードを読む環境を作ってみる」の準備をしてみた

Last updated at Posted at 2017-10-31

Dockerfile

Dockerfile
# サンプルは14.04ベースだったので16.04にしてみた
FROM ubuntu:16.04

# versionをあとで変更しやすいように
ENV MYSQLVER 5.7.20
ENV DEBIAN_FRONTEND=noninteractive

# 日本のミラーサイトのほうが早いのと、build-dep用にdeb-srcの有効化
RUN sed -i \
 -e "s/archive.ubuntu.com/jp.archive.ubuntu.com/g" \
 -e "s/# deb-src/deb-src/g" \
 /etc/apt/sources.list
RUN apt update
RUN apt build-dep -y mysql-server
RUN apt install -y wget curl gdbserver

# mysqlのソース取得
WORKDIR /usr/src
RUN wget "http://ftp.jaist.ac.jp/pub/mysql/Downloads/MySQL-5.7/mysql-boost-${MYSQLVER}.tar.gz"
RUN tar xzf mysql-boost-${MYSQLVER}.tar.gz

# mysqlのソースをdebug付きでビルド
WORKDIR /usr/src/mysql-${MYSQLVER}
RUN CFLAGS=-O0 cmake \
 -DWITH_PIC=1 \
 -DWITH_DEBUG=1 \
 -DWITH_INNODB_EXTRA_DEBUG=1 \
 -DCMAKE_INSTALL_PREFIX="/opt/mysql57" \
 -DDOWNLOAD_BOOST=1 \
 -DWITH_BOOST=./boost
RUN make -j$(getconf _NPROCESSORS_ONLN) install

# my.cnf何かあったほうが良いので、ひな型からコピーしたが、エラー回避用に追加
RUN cp ./packaging/rpm-docker/my.cnf /etc/my.cnf
## 面倒なのでrootで実行します!
RUN sed -i -e "s/user=mysql/user=root/" /etc/my.cnf
RUN echo "explicit_defaults_for_timestamp=true" >> /etc/my.cnf
RUN echo "skip-name-resolve" >> /etc/my.cnf
# mysqld起動用のディレクトリがいくつかないので作成
RUN mkdir /var/lib/mysql-files
RUN mkdir /var/run/mysqld

# mysqldの初期化
RUN /opt/mysql57/bin/mysqld --initialize

EXPOSE 3306
EXPOSE 2345
VOLUME /usr/src

# skip-grant-tablesは、mysql側のアカウント作成の手間を省きたかったため。
CMD gdbserver :2345 /opt/mysql57/bin/mysqld --skip-grant-tables

dockerを動かすホスト

今回は ubuntu17.10 で動かした。

apt install -y docker.io
# vi /etc/group にて現在のユーザーをdockerグループに追加。
# 一度ログアウト、ログインしてdockerグループに属していることを確認。

# mysqlコマンドが必要。もしなければ以下で入れておく。
apt install -y mysql-client
準備
wget "http://ftp.jaist.ac.jp/pub/mysql/Downloads/MySQL-5.7/mysql-5.7.20.tar.gz"
mkdir src
cd src
tar xzf mysql-5.7.20.tar.gz
コンテナ起動
docker run \
 --rm \
 -v $(pwd)/src/mysql-5.7.20:/usr/src/mysql-5.7.20 \
 -v /etc/localtime:/etc/localtime \
 -p 3306:3306 \
 -p 2345:2345 \
 -t --cap-add=SYS_PTRACE --security-opt seccomp=unconfined \
 mysql-debug-5.7 \
 sh -c "
cp /opt/mysql57/bin/mysqld /usr/src/mysql-5.7.20/;
gdbserver :2345 /opt/mysql57/bin/mysqld --skip-grant-tables
"

cp しているのは、ローカルにコピーしたほうが時間の短縮になるため。

# --cap-add=SYS_PTRACE --security-opt seccomp=unconfined をつけなかった場合、以下エラーになる
(gdb) run
Starting program: /usr/local/src/mysql-4.0.30/sql/./gen_lex_hash 
warning: Error disabling address space randomization: Operation not permitted
Cannot create process: Operation not permitted
During startup program exited with code 127.
gdb
$ gdb
...
(gdb) file ./src/mysql-5.7.20/mysqld

# リモートに接続。上で fileを実行していなければ /opt/mysql57/bin/mysqld が読み込まれます。
(gdb) target remote :2345
Remote debugging using :2345
Reading /opt/mysql57/bin/mysqld from remote target...
warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
Reading /opt/mysql57/bin/mysqld from remote target...
Reading symbols from target:/opt/mysql57/bin/mysqld...done.
Reading /lib64/ld-linux-x86-64.so.2 from remote target...
Reading /lib64/ld-linux-x86-64.so.2 from remote target...
Reading symbols from target:/lib64/ld-linux-x86-64.so.2...Reading /lib64/ld-2.23.so from remote target...
Reading /lib64/.debug/ld-2.23.so from remote target...
(no debugging symbols found)...done.
0x00007ffff7dd7c30 in ?? () from target:/lib64/ld-linux-x86-64.so.2

# ローカルとリモートのPATHマッピング http://d.hatena.ne.jp/syasuda/20071208/1197116413
(gdb) set substitute-path /opt/mysql57/ ./src/mysql-5.7.20/

# ブレークポイントを指定
(gdb) b mysql_alter_table

# remoteでmysqldの起動
(gdb) c
接続
/usr/bin/mysql -uroot -h 127.0.0.1
alter tableしてみる
create database test;
use test;
create table test(id int);

alter table test add column no int;

alter table test add column no int;を投入したところ、通常は以下出力となるが

mysql> alter table test add column no int;
Query OK, 0 rows affected (2 min 10.28 sec)
Records: 0  Duplicates: 0  Warnings: 0

以下で止まることを確認。
(gdb) bt でソースファイル名と行番号が出力される。
(gdb) c で停止された処理を続行。

スクリーンショット_2017-10-31_22-47-30.png

ハマリポイント

mysql5.6以降を触っていなかったためmysqlの設定自体でハマった。

TIMESTAMP with implicit DEFAULT value is deprecated

[Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).

これから作るTIMESTAMPは「明示的に NOT NULL 指定」をしない限り「NOT NULL」じゃなくなる。
よってTIMESTAMPについて何も指定していなかったSQLで新しいテーブルに書き込むと現在時刻は自動的に入らず、「NULL」が入ります!

/etc/my.cnf
[mysqld]
explicit_defaults_for_timestamp=true

secure-file-priv設定のエラー

mysqld: Error on realpath() on '/var/lib/mysql-files' (Error 2 - No such file or directory)
[ERROR] Failed to access directory for --secure-file-priv. Please make sure that directory exists and is accessible by MySQL Server. Supplied value : /var/lib/mysql-files

ディレクトリの名前に設定すると、LOAD_FILE() 関数と、LOAD DATA および SELECT ... INTO OUTFILE ステートメントの効果を制限し、そのディレクトリ内のファイルにのみ機能します。

mkdir /var/lib/mysql-files

--initialize

--skip-name-resolve つけないと大量のWARNING

スクリーンショット_2017-10-31_22-02-42.png

/var/run/mysqld がない

mkdir /var/run/mysqld

./src/mysql-5.7.20/data/がない

mkdir ./src/mysql-5.7.20/data/

接続できない

$ /usr/bin/mysql -uroot -h 127.0.0.1
ERROR 1130 (HY000): Host '172.17.0.1' is not allowed to connect to this MySQL server

--skip-grant-tablesオプションが必要だった。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4