导读
作为一个mysql dba, 难免会接触到mysql源码, 光看的话, 不好理解, 效率也不高, 就得改一改, 跑一跑. 那么就需要一个环境. 本文就是来搭建这么一个环境的.
环境准备
需要centos 7.9 能连外网的, 或者有本地的sclo
源也行. 主要是得安装一些依赖包.
编译mysql 8.0.37 需要如下环境, 参考:https://dev.mysql.com/doc/refman/8.0/en/source-installation-prerequisites.html
代码语言:shell复制环境要求:
devtoolset-11-gcc devtoolset-11-gcc-c devtoolset-11-binutils
编译软件版本要求:
GCC >= 10 make >= 3.75 cmake >= 3.11.2
gcc安装要求:
GMP 4.2 , MPFR 3.1.0 and MPC 0.8.0
我们一个个来. 直接整最新的版本.
依赖安装
先安装那一堆开发环境的包.
代码语言:shell复制# 配置sclo yum源
cat <<EOF >/etc/yum.repos.d/base_sclo.repo
[sclo]
name=sclo
baseurl=http://mirrors.tuna.tsinghua.edu.cn/centos-vault/7.9.2009/sclo/x86_64/rh/
enabled=1
gpgcheck=0
EOF
# 安装依赖
yum repolist
yum install devtoolset-11-gcc devtoolset-11-gcc-c devtoolset-11-binutils -y
cmake安装
cmake有二进制的, 我们直接下载就行
代码语言:shell复制mkdir -p ~/cmake
cd ~/cmake
wget https://cmake.org/files/v3.30/cmake-3.30.0-rc1-linux-x86_64.tar.gz
tar -xvf cmake-3.30.0-rc1-linux-x86_64.tar.gz
export PATH=~/cmake-3.30.0-rc1-linux-x86_64/bin:$PATH #就临时配置一下吧. 需要的话, 可以配置 profile
GMP 安装
得编译安装
代码语言:shell复制mkdir -p ~/gmp
cd ~/gmp
wget https://mirror.tuna.tsinghua.edu.cn/gnu/gmp/gmp-6.3.0.tar.gz
tar -xvf gmp-6.3.0.tar.gz
cd gmp-6.3.0
./configure --prefix=/usr/local/gmp-6.3.0
make -j 4 && make install
MPFR 安装
源码编译安装
代码语言:shell复制mkdir -p ~/mpfr
cd ~/mpfr
wget https://mirror.tuna.tsinghua.edu.cn/gnu/mpfr/mpfr-4.2.1.tar.gz
tar -xvf mpfr-4.2.1.tar.gz
cd mpfr-4.2.1
./configure --prefix=/usr/local/mpfr-4.2.1
make -j 4 && make install
MPC 安装
有个小坑是 gcc 做configure的时候找不到mpc.h. 得引入下stdio才行.
代码语言:shell复制mkdir -p ~/mpc
cd ~/mpc
wget https://mirror.tuna.tsinghua.edu.cn/gnu/mpc/mpc-1.3.0.tar.gz
tar -xvf mpc-1.3.0.tar.gz
cd mpc-1.3.0
sed -i '/#include <stdint.h>/a#include <stdio.h>' src/mpc.h # 直接源码里面加上就行.
./configure --prefix=/usr/local/mpc-1.3.0
make -j 4 && make install
GCC 安装
终于安装gcc了
代码语言:shell复制mkdir -p ~/gcc
cd ~/gcc
wget https://mirror.tuna.tsinghua.edu.cn/gnu/gcc/gcc-13.3.0/gcc-13.3.0.tar.gz
tar -xvf gcc-13.3.0.tar.gz
cd gcc-13.3.0
./configure --prefix=/usr/local/gcc-13.3.0
--enable-threads=posix
--disable-checking
--disable-multilib
--enable-languages=c,c
--with-gmp=/usr/local/gmp-6.3.0
--with-mpfr=/usr/local/mpfr-4.2.1/
--with-mpc=/usr/local/mpc-1.3.0/
make -j 4 && make install
编译MYSQL
上面那一大堆步骤都是准备环境, 现在开始编译mysql
代码语言:shell复制mkdir ~/mysql_source
cd ~/mysql_source
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.37-linux-glibc2.17-x86_64.tar.xz
tar -xvf mysql-8.0.37-linux-glibc2.17-x86_64.tar.xz
cd mysql-8.0.37
mkdir bldx86 # 单独一个目录来编译方便点
cd bldx86
cmake .. -DBUILD_CONFIG=mysql_release
make -j 4 #编译很慢
make package #打包(可选, 我们这里就不打包了, 我们还得修改代码呢)
使用
我们直接使用编译好的mysqld来初始化和启动数据库
代码语言:shell复制# 目录创建
mkdir -p /data/mysql_dev/data
mkdir -p /data/mysql_dev/log
mkdir -p /data/mysql_dev/run
# 配置文件整上
cat << EOF > /data/mysql_dev/my.cnf
[mysqld]
user=mysql
bind_address=0.0.0.0
port=3306
basedir=/root/mysql_source/mysql-8.0.37/bldx86
datadir=/data/mysql_dev/data
socket=/data/mysql_dev/run/mysql.sock
pid_file=/data/mysql_dev/run/mysql.pid
tmpdir=/data/mysql_dev/run
log_error=/data/mysql_dev/log/mysql.err
log_bin=/data/mysql_dev/log/mysql-bin
EOF
chown mysql:mysql /data/mysql_dev -R
# 初始化
/root/mysql_source/mysql-8.0.37/bldx86/runtime_output_directory/mysqld --defaults-file=/data/mysql_dev/my.cnf --initialize-insecure
# 启动 (--daemonize 也可以放后台)
nohup /root/mysql_source/mysql-8.0.37/bldx86/runtime_output_directory/mysqld --defaults-file=/data/mysql_dev/my.cnf &
# 修改密码(第一次要改密码)
mysql -S /data/mysql_dev/run/mysql.sock # 使用socket登录
alter user root@'localhost' identified with mysql_native_password by '123456'; -- 第一次登录必须先修改密码
create user root@'%' identified with mysql_native_password by '123456'; -- 建个普通用户方便我们使用
grant all on *.* to root@'%'; -- 这个用户其实也不普通
flush privileges;
# 停止
kill `cat /data/mysql_dev/run/mysql.pid`
# 配置成脚本或者服务更方便, 按照自己的习惯来吧, 我这里就不提供了.
调试演示
上面的步骤都完成之后, 就得到了一个调试环境. 可以修改源码,然后编译验证了.
演示一下吧, 我们知道 mysqld 启动的时候会自动启动主从复制进程. 那么我们可以修改源码来不让它自动启动.
编辑 sql/mysqld.cc
中的 mysqld_main 函数里面关于主从启动的代码. 简单点, 我们直接加个opt_skip_replica_start=true
, 即相当于默认加上 --skip-slave-start
.
在 replica_initializer
之前加上就行. 比如:
opt_skip_replica_start = true; /* 不启动主从 */
check_binlog_cache_size(nullptr);
check_binlog_stmt_cache_size(nullptr);
binlog_unsafe_map_init();
ReplicaInitializer replica_initializer(opt_initialize, opt_skip_replica_start,
rpl_channel_filters,
&opt_replica_skip_errors);
然后重新编译(make -j 4
), 之后编译修改的部分, 然后重新组装到mysqld里面
[ 87%] Built target routertest_component_mock_server
[ 87%] Built target sql_gis
[ 87%] Building CXX object sql/CMakeFiles/sql_main.dir/mysqld.cc.o
[ 87%] Linking CXX static library ../archive_output_directory/libsql_main.a
[ 93%] Built target sql_main
[ 96%] Built target innobase
[ 96%] Linking CXX shared library library_output_directory/libserver_unittest_library.so
[ 96%] Linking CXX executable ../runtime_output_directory/mysqld
[ 96%] Built target mysqld
[ 96%] Built target INFO_BIN
[ 96%] Built target server_unittest_library
[ 96%] Linking CXX executable ../../../runtime_output_directory/pfs_connect_attr-t
[ 96%] Linking CXX executable ../../../runtime_output_directory/merge_keyring_file_tests-t
[ 96%] Linking CXX executable ../../../runtime_output_directory/merge_innodb_tests-t
[ 96%] Linking CXX executable ../../runtime_output_directory/merge_large_tests-t
[ 96%] Built target pfs_connect_attr-t
[ 96%] Linking CXX executable ../../../../plugin_output_directory/minimal_chassis_test_driver-t
[ 96%] Built target merge_keyring_file_tests-t
[ 96%] Linking CXX executable ../../../../plugin_output_directory/reference_cache-t
[ 96%] Built target minimal_chassis_test_driver-t
[ 96%] Linking CXX executable ../../../runtime_output_directory/group_replication_member_info-t
[ 96%] Built target reference_cache-t
[ 96%] Linking CXX executable ../../../runtime_output_directory/group_replication_compatibility_module-t
[ 96%] Built target group_replication_member_info-t
[ 96%] Linking CXX executable ../../../runtime_output_directory/group_replication_member_version-t
[ 96%] Built target merge_innodb_tests-t
[ 97%] Linking CXX executable ../../../runtime_output_directory/group_replication_mysql_version_gcs_protocol_map-t
[ 97%] Built target group_replication_compatibility_module-t
[ 97%] Linking CXX executable ../../../runtime_output_directory/group_replication_gcs_mysql_network_provider-t
[ 97%] Built target group_replication_member_version-t
[ 97%] Linking CXX executable ../../../runtime_output_directory/merge_temptable_tests-t
[ 97%] Built target group_replication_mysql_version_gcs_protocol_map-t
[ 97%] Linking CXX executable ../../../runtime_output_directory/gtid_set-t
[ 97%] Built target group_replication_gcs_mysql_network_provider-t
[ 97%] Built target merge_temptable_tests-t
[ 97%] Built target gtid_set-t
[100%] Built target merge_large_tests-t
16:27:38 [root@ddcw21 bldx86]#make -j 4
然后再次启动mysqld 发现就没得之前的那些repl信息了
登录数据库确认一下: 主从进程没启动(也没报错)
代码语言:sql复制(root@127.0.0.1) [(none)]> show slave statusG
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 192.168.101.21
Master_User: repl
Master_Port: 3314
Connect_Retry: 60
Master_Log_File:
Read_Master_Log_Pos: 4
Relay_Log_File: ddcw21-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File:
Slave_IO_Running: No
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 0
Relay_Log_Space: 697
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 0
Master_UUID:
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State:
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set, 1 warning (0.00 sec)
总结
至此我们就得到了一个mysql的调试环境, 可以随便调试了.
编程语言其实基本上都差不多的, 会一门语言, 其它的基本上就能看懂, 然后慢慢调试, 慢慢理解.