KylinV10装GreatSQL,这几年国产化项目里越来越常见。我最近刚好在一套银河麒麟V10服务器上部署了一次,业务要求把现有数据库切换到GreatSQL。因为原系统是MySQL生态,迁移成本低,而且GreatSQL在MySQL 8.0的基础上做了不少优化,尤其在并行复制和MGR(组复制)方面更适合国产化场景。安装方式我直接选了二进制包,没有用源码编译,也没有用RPM。源码编译在Kylin上依赖链时容易出问题,RPM则往往跟系统的包管理版本绑定,不够灵活。二进制包解压就能用,路径自己可控,正好适合这类定制化部署。
这次实测下来整体流程不复杂,但中间有几个坑比较冷门,比如依赖库缺失、SELinux上下文、systemd服务启动时的目录权限等。这篇就把从环境确认、依赖安装、目录初始化、服务配置到常见问题排查的完整过程整理出来,给后面要上手的人一个参考。
1. 安装方式选型与KylinV10环境确认
1.1 三种安装方式对比
在Linux上装MySQL系数据库,常见无非三种:系统包管理器安装、源码编译、二进制包解压。RPM/DNF方式安装最省事,但目录跟随发行版约束,想调整数据目录或配置路径时比较拧巴;源码编译可以深度定制,但耗时长,而且对编译器、CMake版本有要求,在KylinV10这类系统上万一缺某个依赖,排查起来非常痛苦。
二进制包是我在这种场景下的优先选择。它本质上是官方或发行版预先编译好的可执行文件集合,自带mysqld、mysql、mysqladmin等工具,解压后经过简单配置就能跑起来。好处有三个:目录结构完全可控,方便做数据目录与程序目录分离;升级时直接替换整个目录,回滚也容易;不受系统包管理仓库版本限制,想用哪个版本就用哪个版本。
我这次用的GreatSQL二进制包版本是8.0.x系列,压缩包大概几百MB,里面自带lib目录下所需的运行库。它针对glibc有版本要求,所以安装前先确认系统环境。
1.2 检查系统版本与内核
先确认系统是不是KylinV10,以及CPU架构。命令很简单:
cat /etc/os-release uname -m我这边输出是Kylin Linux V10,架构x86_64。官方二进制包一般提供x86_64和aarch64两种,确认架构后别下载错包。接着看内核版本和glibc版本,因为二进制包编译时依赖特定glibc版本,太低会直接报version 'GLIBC_2.XX' not found:
uname -r ldd --version | head -n1KylinV10基于OpenEuler或CentOS的技术路线演进,glibc版本通常比较新,一般都能满足要求。如果后面启动时报GLIBC缺失,那就需要检查是不是下载成了其他发行版编译的包。
依赖库方面,MySQL系数据库需要libaio、numactl-libs这些。先查一下:
rpm -qa | grep libaio rpm -qa | grep numactl缺了就用dnf install -y libaio numactl-libs补上。这个在KylinV10上直接装即可,不要跳过,我就遇到过少装libaio导致mysqld启动后立刻退出,日志里只有error while loading shared libraries之类的报错。
2. 二进制包解压部署与运行目录规划
2.1 获取安装包并校验完整性
从GreatSQL官方或镜像站下载二进制包,然后一定要做校验。我习惯先用sha256sum对比官方提供的校验值,防止下载损坏或被篡改:
sha256sum greatsql-8.0.32-25-linux-glibc2.17-x86_64.tar.xz官方页面会给一个sha256值,两边一致再解压。这一步别偷懒,我的经验是至少出现过一次下载文件损坏,解压能成功但启动时段错误。
解压到规划好的目录。我习惯把程序目录放在/opt下,然后做一个软链,这样以后升级可以直接替换软链指向,路径不用变:
tar -xf greatsql-8.0.32-25-linux-glibc2.17-x86_64.tar.xz -C /opt mv /opt/greatsql-8.0.32-25-linux-glibc2.17-x86_64 /opt/greatsql这里有个细节:官方压缩包解压后的目录名很长,重命名成简短的/opt/greatsql,后续配置路径清爽很多。如果目录名带版本号,将来版本升级还要改配置,不划算。
2.2 创建专用用户与数据目录
数据库运行不能直接使用root账号,这是安全底线。创建专用用户,并规划数据目录:
groupadd mysql useradd -r -g mysql -s /bin/false mysql mkdir -p /data/mysql/data mkdir -p /data/mysql/logs chown -R mysql:mysql /data/mysql数据目录单独放一块盘,不要和系统盘混在一起。这是我在生产环境被教育过的事,系统盘空间一旦被日志占满,整个服务器都可能卡死。数据盘挂载点可能是/data,也可能是根据业务规划的其他路径,但一定要单独分区,别用根目录。
程序目录和数据目录分离之后,还需要给/opt/greatsql设置权限:
chown -R root:root /opt/greatsql程序目录归root所有,普通用户无写权限,防止启动用户篡改二进制文件。但数据目录、日志目录归mysql用户。
2.3 配置环境变量与基础脚本
GreatSQL二进制包里自带bin和support-files目录。我通常把/opt/greatsql/bin加入PATH,方便直接执行mysql命令:
echo 'export PATH=/opt/greatsql/bin:$PATH' >> /etc/profile.d/greatsql.sh source /etc/profile.d/greatsql.shsupport-files里有mysql.server脚本,可以用来启停服务。不过我更推荐后面用systemd管理,后面会细说。在这之前先检查一下mysqld的版本:
mysqld --version能正常输出版本号,说明二进制文件在当前系统上可以运行,依赖问题基本解决。如果这里报libaio缺失或者GLIBC错误,趁早补依赖,不要等到初始化再排错。
3. 配置文件编写与数据目录初始化
3.1 关键配置说明
GreatSQL的配置文件默认路径是/etc/my.cnf。对于二进制包,官方会使用编译时的默认路径,所以自己写一个/etc/my.cnf即可。我的基础配置如下:
[mysqld] user = mysql basedir = /opt/greatsql datadir = /data/mysql/data socket = /data/mysql/mysql.sock pid-file = /data/mysql/mysql.pid log-error = /data/mysql/logs/error.log port = 3306 server-id = 1 character-set-server = utf8mb4 collation-server = utf8mb4_0900_ai_ci # 连接与并发 max_connections = 300 back_log = 128 # InnoDB innodb_buffer_pool_size = 2G innodb_log_file_size = 512M innodb_flush_log_at_trx_commit = 2 sync_binlog = 1 # binlog log-bin = /data/mysql/logs/binlog binlog_format = ROW max_binlog_size = 256M expire_logs_days = 15解释几个需要特别注意的点:
socket放在datadir下,不要放到/tmp。有些场景/tmp有清理策略,socket文件没了客户端就连不上,到时候排查很绕。innodb_buffer_pool_size一般为物理内存的60%-70%,我这里机器内存在8G左右,所以给2G,可以根据实际调整。innodb_flush_log_at_trx_commit = 2配合sync_binlog = 1是常见组合,兼顾性能与安全,如果对数据安全要求极高,可以改成innodb_flush_log_at_trx_commit = 1,但性能会降低。expire_logs_days在MySQL 8.0中已标记为废弃,应该使用binlog_expire_logs_seconds,但GreatSQL的8.0.32版本仍兼容旧参数,我习惯用binlog_expire_logs_seconds = 1296000(15天)。
配置文件写好后,可以用mysqld --validate-config校验一下:
/opt/greatsql/bin/mysqld --defaults-file=/etc/my.cnf --validate-config这个命令只检查配置语法,不启动服务。有错误会直接输出,省得初始化时才发现问题。
3.2 初始化数据目录
初始化方式有两种:mysqld --initialize和mysqld --initialize-insecure。前者会生成一个随机临时密码在error log里,后者不生成密码,root账号是空密码。我推荐用--initialize-insecure,因为初始化后可以直接登录再设密码,不用去日志里翻临时密码。命令如下:
/opt/greatsql/bin/mysqld --defaults-file=/etc/my.cnf --initialize-insecure --user=mysql执行完检查error log:
tail -n 50 /data/mysql/logs/error.log正常情况下能看到类似[Note] Execution of init_connect_server_authentication completed之类的提示,没有ERROR。注意,初始化只能执行一次,如果目录里已经有数据再执行,会报错Data dictionary initialization failed,所以初始化前确保数据目录是空的。
3.3 配置systemd服务
用systemd管理比直接跑mysqld_safe更符合现代运维方式,能查看状态、设置开机自启、崩溃自动拉起。在/etc/systemd/system下创建greatsql.service:
[Unit] Description=GreatSQL Server After=network.target [Service] User=mysql Group=mysql Type=simple ExecStart=/opt/greatsql/bin/mysqld --defaults-file=/etc/my.cnf LimitNOFILE=65535 Restart=on-failure RestartSec=5s TimeoutSec=300 [Install] WantedBy=multi-user.target这里注意Type=simple,不要写成Type=forking。mysqld_safe是forking风格,但直接执行mysqld就是simple,PID由systemd跟踪。重启策略用on-failure,不要用always,否则遇到配置错误反复重启反而麻烦。
然后加载并启动:
systemctl daemon-reload systemctl start greatsql systemctl status greatsql启动后检查进程:
ps -ef | grep mysqld端口监听确认:
ss -lnt | grep 3306接着设置开机自启:
systemctl enable greatsql到这一步,数据库基本跑起来了。
4. 安全配置与远程访问设置
4.1 root账号初始化与安全加固
初始化时选了--initialize-insecure,root目前是空密码,必须设置强密码。进入数据库:
mysql -uroot -S /data/mysql/mysql.sock执行:
ALTER USER 'root'@'localhost' IDENTIFIED BY '你的强密码'; FLUSH PRIVILEGES;注意,MySQL 8.0默认还在mysql.user表里保留了空密码账号,必须处理:
SELECT user, host FROM mysql.user;如果有多余的匿名账号,删掉:
DROP USER IF EXISTS ''@'localhost'; DROP USER IF EXISTS 'root'@'127.0.0.1';只保留root@localhost和必要的账号即可。这里有个坑:root@localhost只允许本机通过socket连接,如果你还想本机用TCP连,可以创建root@127.0.0.1。不过更稳妥的做法是创建指定业务的专用账号,而不是开放root远程登录。
4.2 创建业务账号与授权
给业务系统建一个最小权限账号,是生产环境的基本礼貌。比如:
CREATE USER 'app_user'@'10.0.0.%' IDENTIFIED BY 'App_Password#123'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, REFERENCES ON `business_db`.* TO 'app_user'@'10.0.0.%'; FLUSH PRIVILEGES;授予权限要按需给,不要动不动就ALL PRIVILEGES。遇到过开发同学拿到的账号有超级权限,误删整表之后还在binlog里找不到,因为连DROP都被允许了。最小权限原则,既能防止误操作,也便于事后审计。
4.3 防火墙端口放行
KylinV10默认可能启用了firewalld。远程连不上,多半是防火墙挡了3306端口。先查看:
systemctl status firewalld如果启用状态,放行端口:
firewall-cmd --permanent --add-port=3306/tcp firewall-cmd --reload严谨一点的话,最好限定来源IP段,而不是对全网放开:
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" port protocol="tcp" port="3306" accept' firewall-cmd --reload如果公司内部有堡垒机或安全组,防火墙不一定需要开,但本地firewalld还是查一下,这是最容易踩的坑。曾经有个部署案例,数据库启动正常,端口也在监听,但业务端就是连不上,折腾半天才发现是firewalld默认zone阻止了宿主机外部访问,放行后立好。
4.4 SELinux影响说明
KylinV10默认SELinux可能是enforcing状态。如果mysqld进程绑定端口被拒绝,或者读写数据目录被拒绝,即便文件权限正确也可能出问题。
可以先查看SELinux状态:
getenforce如果返回Enforcing,再看mysqld进程是否被限制。比较省事的做法是直接对MySQL相关目录设置正确上下文:
semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?" restorecon -Rv /data/mysqlrestorecon后,在ls -Z里能看到文件上下文变成mysqld_db_t。这样SELinux就不会拦程序读写数据目录了。另一个方案是直接设置SELinux布尔值,比如:
setsebool -P mysqld_connect_all 1这类布尔值需要根据具体策略调整。如果实在搞不定,可以临时setenforce 0排查,但生产环境不建议关闭SELinux,保持默认开启更重要。我在项目中遇到过SELinux启用时mysqld无法创建socket文件,确认权限无误,一查上下文是默认的var_t,改成mysqld_var_run_t后重启即可。
5. 常见故障与排查实录
5.1 启动失败:找不到共享库
启动时systemctl status提示进程退出,先看日志:
journalctl -u greatsql -n 50如果出现error while loading shared libraries: libaio.so.1: cannot open shared object file,说明依赖库缺失。安装即可:
dnf install -y libaio如果装完之后还是提示找不到,可能是64位系统下库路径问题,可以用ldconfig刷新缓存,或者把/usr/lib64加入/etc/ld.so.conf。也有一种情况:下载的GreatSQL二进制包是aarch64的,但系统是x86_64,也会报这类错误,所以下载前一定要确认架构。
5.2 初始化时报目录不可写
初始化时如果出现Can't create/write to file '/data/mysql/data/xxx',优先检查目录属主:
ls -ld /data/mysql/data正常应该是mysql:mysql。如果属主是root,就chown -R mysql:mysql /data/mysql。还有一种隐蔽情况:数据目录所在分区上加了nosuid之类的挂载选项,虽然不常见,但KylinV10部分环境下/data挂载参数可能限制文件创建。可以用touch /data/mysql/testfile实测一下。
另外一个容易忽略的是/etc/my.cnf里配置的socket、pid-file、log-error路径。如果这些路径的父目录不存在,mysqld也会初始化失败。我习惯先创建好日志目录再启动。
5.3 服务启动后端口不监听
启动成功后ss -lnt看不到3306,但进程还在。这种情况多半是配置了bind-address,比如默认bind-address=127.0.0.1,只监听回环地址。检查配置:
grep bind-address /etc/my.cnf如果是想允许远程访问,设置:
bind-address = 0.0.0.0或者指定业务网卡的IP。这里提醒一下,bind-address=0.0.0.0表示监听所有网卡,配合防火墙限制来源IP更安全。
另一个可能是validate_password插件导致初始化时创建密码策略不符?那不会导致端口不监听。端口不监听还是集中在网络配置。
5.4 客户端连接时报Access denied
用mysql -h 服务器IP -P 3306 -u账号 -p连接时,报Access denied for user 'xx'@'xx',分几种情况:
- 账号确实不存在,需要在数据库里创建并授权。
- host匹配问题:MySQL按user表中的host精确匹配,比如创建的是
'app_user'@'10.0.0.%',但客户端IP是192.168.1.10,那就匹配不上,会拒绝连接。核查客户端实际IP,然后创建对应host。 - root默认只允许localhost,所以不要用root远程连接。很多初学者习惯直接用root,在配置里改成remote root,这是不推荐的。
5.5 数据目录损坏恢复思路
数据目录有时因为掉电、磁盘异常导致InnoDB文件损坏,启动日志里能看到Database page corruption或者InnoDB: Corruption of a page。这种情况先别着急删数据,尝试备份数据目录,然后从近期全量备份恢复。如果配置了主从复制,也可以从从库提升。
在没有备份的情况下,可以尝试innodb_force_recovery模式启动,配置:
[mysqld] innodb_force_recovery = 1从1到6逐级尝试,级别越高越激进,启动后尽快把数据导出来,然后重建实例。注意,用了innodb_force_recovery后只能读不能正常写,是救急手段,不是日常配置。
5.6 常见问题速查表
| 现象 | 可能原因 | 快速处理 |
|---|---|---|
| 启动后进程消失 | libaio缺失、配置路径错误 | journalctl查日志,补依赖、修正路径 |
| 初始化失败 | 数据目录非空、目录权限 | 清空目录、chown mysql |
| 远程连接超时 | 防火墙拦截、服务未监听 | firewall-cmd放行端口、检查bind-address |
| Access denied | host不匹配、账号权限 | 核查mysql.user,调整账号host或授权 |
| MySQL CPU高 | 慢查询、全表扫描 | 开慢查询日志、EXPLAIN分析SQL |
| 磁盘占用高 | binlog积压 | 确认binlog过期时间,清理历史日志 |
6. 一点个人经验补充
最后分享几个部署之外的小心得,都是实际项目中总结出来的。
第一个是初始化之前一定要先确认磁盘空间。df -h看数据盘剩余空间,如果日志盘和数据盘独立,那日志文件大小也要提前规划。我之前遇到过一次数据盘只有20G,结果加载全量业务数据时直接撑满,数据库进入只读模式,业务全面告警。所以部署前预留30%以上空余空间是底线。
第二个是建议把mysql和mysqldump客户端的配置文件也维护好。比如在/etc/my.cnf里增加client配置段:
[client] socket = /data/mysql/mysql.sock这样本机执行mysql命令就不用每次指定socket,也更不容易搞混。
第三个是关于升级。GreatSQL版本更新较快,二进制包的升级流程其实就是新包解压、停服务、替换软链、启动。替换前停服务是必须的,同时备份老版本目录,不要图省事直接覆盖。我在演示环境里试过直接覆盖,结果新旧数据字典不兼容,启动报错,最后只能回滚。如果版本跨度大(比如8.0.25升到8.0.32),建议先跑mysqld --all-databases全量备份,再走测试库升级演练。
第三个其实多说一点:GreatSQL在MGR(组复制)方向上做了很多优化,如果你准备搭建高可用集群,建议直接使用GreatSQL官方推荐的mgr相关配置,这些在官方文档里有详细的参数说明。二进制包自带的数据字典兼容MySQL 8.0,从MySQL原版迁移过来基本无感,但要注意版本号对应,比如GreatSQL 8.0.32对应MySQL 8.0.32,逻辑复制等功能可以平滑使用。
如果只是单机部署,看到本文的位置基本已经够用了。KylinV10上跑GreatSQL并不神秘,跟传统Linux装MySQL系数据库思路一致,注意依赖、权限、SELinux和systemd配置这些细节,不贪快,按步骤来,基本一次就能通过。后面如果有高可用、主从复制相关的部署经验,我再单独写一篇。