MySQL安装教程:图文教程从零开始,手把手教你搭建稳定高效的数据库环境

对于开发者、运维人员乃至刚入门的IT从业者来说,MySQL几乎是绕不开的第一关。无论是搭建个人博客、企业官网,还是开发复杂的业务系统,MySQL作为全球最流行的开源关系型数据库,凭借其稳定、高效、免费的特性,始终是后端存储方案的首选。

本文将以CentOS 7系统为例,采用MySQL二进制安装方式,从环境检查、版本选择,到安装执行、安全初始化、远程访问开启、启动报错的排查,每一步都配有完整命令和注释。读完这篇教程,你不仅能顺利装好MySQL,更将理解每个配置背后的逻辑,真正做到“装得对、用得好、排得了错”。

适用人群:运维工程师、后端开发、云服务器使用者、Linux初学者
前置要求:一台CentOS 7服务器,如果还没有,可以参考我前面的文章,VMware安装centos教程:https://www.cnblogs.com/dbbull/p/20891421

一、Linux安装MySQL规范

1.1 MySQL安装方式

  • 推荐方式:二进制安装(tar 包解压即用)
  • 其他方式:源码编译、Yum、RPM(不展开)

1.2 MySQL 运行用户

  • 使用虚拟用户 mysql:mysql,仅用于进程运行,禁止登录不创建家目录
  • 创建命令:
    useradd -s /sbin/nologin -M mysql
    

1.3 MySQL目录规范

用途 路径示例
下载目录 /server/tools
系统目录 /opt/mysql/mysql-8.0.45
软链接 ln -s /opt/mysql/mysql-8.0.45 /usr/local/mysql
数据目录 /data/mysql/mysql3306/{data,logs}
配置文件 /data/mysql/mysql3306/my3306.cnf

1.4 MySQL安装依赖环境检查

  • GNU libc 版本 必须 ≥ 2.17(否则启动报错)
  • 查看命令:
  ldd --version
  示例输出:
ldd (GNU libc) 2.17
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
由 Roland McGrath 和 Ulrich Drepper 编写。

二、Linux安装 MySQL 8.0(完整步骤)

下载MySQL8.0安装包(不要选择过低的版本,后面的版本会修复已知的bug,过低的版本bug较多,谨慎选择)

通过网盘分享的文件:mysql-8.0.45-linux-glibc2.17-x86_64
链接: https://pan.baidu.com/s/1DBY3D1h2Up4z-jMemxNSuA?pwd=5xib 提取码: 5xib 
--来自百度网盘的分享

2.1 准备工作

# 1. 创建虚拟用户
useradd -s /sbin/nologin -M mysql

Linux安装MySQL教程

# 2. 创建所需目录
mkdir -p /server/tools
mkdir -p /opt/mysql
mkdir -p /data/mysql/mysql3306/{data,logs}

Linux安装MySQL教程

# 3. 进入下载目录
cd /server/tools
# 4. 上传二进制包(若没有 lrzsz,先 yum install -y lrzsz)
rz

Linux安装MySQL教程

💡 课堂小技巧

  • 快速备份:cp a.txt{,.bak}
  • 删除文件前先用 mv 移到 /tmp,确认无用后再删除,避免误删。

2.2 解压与移动

# 解压(包名以实际为准)
tar xf mysql-8.0.45-linux-glibc2.17-x86_64.tar.xz

Linux安装MySQL教程

# 移动到规范目录
mv mysql-8.0.45-linux-glibc2.17-x86_64 /opt/mysql/mysql-8.0.45

Linux安装MySQL教程

# 创建软链接
ln -s /opt/mysql/mysql-8.0.45 /usr/local/mysql

Linux安装MySQL教程

2.3 移除系统自带 MariaDB(避免冲突)

rpm -e --nodeps mariadb-libs

Linux安装MySQL教程

2.4 编辑配置文件

vim /data/mysql/mysql3306/my3306.cnf

配置内容(参考):

[mysqld]
user=mysql
basedir=/usr/local/mysql
datadir=/data/mysql/mysql3306/data
socket=/data/mysql/mysql3306/mysql.sock
server_id=1
port=3306
log_error=/data/mysql/mysql3306/logs/error.log
log_bin=/data/mysql/mysql3306/logs/mysql-bin
binlog_format=row
gtid_mode=on
enforce_gtid_consistency=true
log_slave_updates=1
max_connections=1024
wait_timeout=60
sort_buffer_size=2M
max_allowed_packet=32M
join_buffer_size=2M
innodb_buffer_pool_size=128M
innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=32M
innodb_log_file_size=128M
innodb_log_files_in_group=2
binlog_cache_size=2M
max_binlog_cache_size=8M
max_binlog_size=512M
expire_logs_days=7
slow_query_log=on
slow_query_log_file=/data/mysql/mysql3306/logs/slow.log
long_query_time=0.5
log_queries_not_using_indexes=1

Linux安装MySQL教程

2.5 安装依赖包

yum install libaio-devel numactl -y

Linux安装MySQL教程

2.6 更改目录权限

chown -R mysql:mysql /data/*

Linux安装MySQL教程

2.7 初始化数据库(空密码)

/usr/local/mysql/bin/mysqld \
  --defaults-file=/data/mysql/mysql3306/my3306.cnf \
  --initialize-insecure \
  --user=mysql \
  --basedir=/usr/local/mysql \
  --datadir=/data/mysql/mysql3306/data

--initialize-insecure 表示 root 密码为空;若用 --initialize 则生成随机密码并记录在 error.log。

Linux安装MySQL教程

2.8 配置环境变量

echo 'PATH="/usr/local/mysql/bin:$PATH"' >> /etc/profile
source /etc/profile

Linux安装MySQL教程

2.9 启动 MySQL

mysqld --defaults-file=/data/mysql/mysql3306/my3306.cnf &

2.10 验证启动

netstat -lntup | grep mysql

Linux安装MySQL教程


三、连接 MySQL 的方式

  • 本地连接(使用 socket):
    无需输入密码,回车即可连接
    mysql -uroot -p -S /data/mysql/mysql3306/mysql.sock
    

Linux安装MySQL教程

  • 远程连接(TCP/IP):
    默认没有远程连接的用户,需要单独创建
    mysql> create user root@'%' identified by '123456';
    Query OK, 0 rows affected (0.04 sec)
    
    mysql> grant all on *.* to root@'%';
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> mysql -uroot -p -P3306 -h192.168.80.80
    

15


四、常用sql语句

4.1. 数据库操作

-- 创建数据库(指定字符集)
CREATE DATABASE IF NOT EXISTS mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 查看所有数据库
SHOW DATABASES;

-- 切换/使用数据库
USE mydb;

-- 查看当前所在数据库
SELECT DATABASE();

-- 删除数据库(谨慎操作)
DROP DATABASE IF EXISTS mydb;

4.2. 建表语句(含各类约束)

-- 标准建表(主键、自增、默认值、注释、唯一约束、外键)
CREATE TABLE IF NOT EXISTS `users` (
  `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '用户ID(主键)',
  `username` VARCHAR(50) NOT NULL COMMENT '用户名',
  `email` VARCHAR(100) NOT NULL COMMENT '邮箱',
  `phone` VARCHAR(20) DEFAULT NULL COMMENT '手机号',
  `password_hash` VARCHAR(255) NOT NULL COMMENT '密码哈希',
  `age` TINYINT(3) UNSIGNED DEFAULT 0 COMMENT '年龄',
  `salary` DECIMAL(10,2) DEFAULT 0.00 COMMENT '月薪',
  `status` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '状态:1启用 0禁用',
  `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_username` (`username`),           -- 唯一索引
  UNIQUE KEY `uk_email` (`email`),
  KEY `idx_status_created` (`status`, `created_at`) -- 联合普通索引
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';

-- 创建关联表(带外键)
CREATE TABLE `orders` (
  `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `user_id` INT(11) UNSIGNED NOT NULL COMMENT '关联用户ID',
  `amount` DECIMAL(10,2) NOT NULL,
  `order_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_user_id` (`user_id`),
  CONSTRAINT `fk_orders_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

4.3. 表结构修改(ALTER TABLE)

-- 添加列
ALTER TABLE users ADD COLUMN `address` VARCHAR(200) DEFAULT NULL COMMENT '地址';

-- 修改列类型/属性
ALTER TABLE users MODIFY COLUMN `phone` VARCHAR(30) NOT NULL COMMENT '手机号';

-- 修改列名(同时改类型)
ALTER TABLE users CHANGE `phone` `mobile` VARCHAR(20) NOT NULL COMMENT '手机号';

-- 删除列
ALTER TABLE users DROP COLUMN `address`;

-- 添加索引
ALTER TABLE users ADD INDEX idx_age (`age`);
ALTER TABLE users ADD UNIQUE INDEX uk_phone (`mobile`);

-- 删除索引
ALTER TABLE users DROP INDEX idx_age;

-- 重命名表
RENAME TABLE users TO user_info;
-- 或
ALTER TABLE user_info RENAME TO users;

-- 查看表结构
DESC users;
-- 或查看建表语句
SHOW CREATE TABLE users;

4.4. 清空表(两种方式区别大)

-- 方式1:删除所有数据,保留表结构,自增计数器归零,可回滚(事务内)
DELETE FROM users;

-- 方式2:清空表,自增计数器归零,速度极快,不可回滚(DDL操作)
TRUNCATE TABLE users;

4.5. INSERT(插入)

-- 标准插入(指定列)
INSERT INTO users (username, email, password_hash, age, salary) 
VALUES ('zhangsan', 'zhangsan@example.com', 'hash123', 28, 8500.00);

-- 批量插入(推荐,效率高)
INSERT INTO users (username, email, password_hash, age) VALUES 
('lisi', 'lisi@example.com', 'hash456', 32),
('wangwu', 'wangwu@example.com', 'hash789', 25);

-- 插入时遇到重复键则更新(ON DUPLICATE KEY UPDATE)
INSERT INTO users (username, email, password_hash, age) 
VALUES ('zhangsan', 'newemail@example.com', 'newhash', 29)
ON DUPLICATE KEY UPDATE 
  email = VALUES(email), 
  age = VALUES(age);

-- 插入时忽略重复键(不报错)
INSERT IGNORE INTO users (username, email, password_hash) 
VALUES ('zhangsan', 'dup@example.com', 'xxx');

4.6. UPDATE(更新)

-- 更新单条(务必带WHERE,否则全表更新!)
UPDATE users SET age = 30, salary = 9000.00 WHERE username = 'zhangsan';

-- 条件更新(CASE WHEN)
UPDATE users 
SET salary = CASE 
  WHEN age < 25 THEN salary * 1.2
  WHEN age BETWEEN 25 AND 35 THEN salary * 1.1
  ELSE salary * 1.05
END;

-- 联表更新(用JOIN)
UPDATE users u
JOIN orders o ON u.id = o.user_id
SET u.status = 0
WHERE o.amount < 10.00;

4.7. DELETE(删除)

-- 删除指定条件数据
DELETE FROM users WHERE age > 60 AND status = 0;

-- 联表删除(删除无订单的用户)
DELETE u FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE o.id IS NULL;

-- 安全删除:先查询确认再删除(善用事务)
START TRANSACTION;
SELECT * FROM users WHERE age > 60;  -- 先看看要删哪些
DELETE FROM users WHERE age > 60;
-- 确认无误后 COMMIT; 有问题则 ROLLBACK;

4.8. 基础查询

-- 查询所有列(生产环境不推荐 *)
SELECT * FROM users;

-- 查询指定列 + 别名
SELECT id, username AS 用户名, email AS 邮箱 FROM users;

-- 去重查询
SELECT DISTINCT status FROM users;

-- 条件查询(WHERE)
SELECT * FROM users 
WHERE age >= 18 AND age <= 30 AND status = 1;

-- IN / NOT IN
SELECT * FROM users WHERE id IN (1, 3, 5, 7);
SELECT * FROM users WHERE status NOT IN (0, 2);

-- BETWEEN
SELECT * FROM users WHERE age BETWEEN 20 AND 35;

-- LIKE 模糊查询(%任意字符,_单个字符)
SELECT * FROM users WHERE username LIKE '张%';  -- 以"张"开头
SELECT * FROM users WHERE email LIKE '%@qq.com'; -- QQ邮箱

-- NULL 值判断(不能用 = NULL)
SELECT * FROM users WHERE phone IS NULL;
SELECT * FROM users WHERE phone IS NOT NULL;

4.9. 排序、分页

-- ORDER BY(升序ASC默认,降序DESC)
SELECT * FROM users WHERE status = 1 
ORDER BY age DESC, created_at ASC;

-- 分页查询(LIMIT offset, count)
SELECT * FROM users ORDER BY id DESC LIMIT 0, 20;   -- 第1页(每页20条)
SELECT * FROM users ORDER BY id DESC LIMIT 20, 20;  -- 第2页

-- 优化大偏移量分页(记录上一页最后一条ID)
SELECT * FROM users WHERE id > 1000 ORDER BY id LIMIT 20;

4.10. 聚合函数 + GROUP BY + HAVING

-- 常用聚合:COUNT, SUM, AVG, MAX, MIN
SELECT 
  COUNT(*) AS total_users,
  AVG(age) AS avg_age,
  MAX(salary) AS max_salary,
  MIN(salary) AS min_salary,
  SUM(salary) AS total_salary
FROM users WHERE status = 1;

-- GROUP BY 分组统计
SELECT 
  status,
  COUNT(*) AS count,
  AVG(age) AS avg_age
FROM users
GROUP BY status;

-- HAVING 对分组结果过滤(区别于WHERE)
SELECT 
  status,
  COUNT(*) AS cnt
FROM users
GROUP BY status
HAVING cnt > 10;  -- 只返回人数 > 10 的状态组

4.11. 多表连接查询(JOIN)

-- INNER JOIN(取交集)
SELECT u.username, o.amount, o.order_time
FROM users u
INNER JOIN orders o ON u.id = o.user_id
WHERE o.amount > 100;

-- LEFT JOIN(左表全保留,右表无匹配则为NULL)
SELECT u.username, COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.username;

-- 自连接(查询同一张表的上下级关系)
SELECT 
  e1.username AS employee,
  e2.username AS manager
FROM users e1
LEFT JOIN users e2 ON e1.manager_id = e2.id;

-- 子查询(WHERE中)
SELECT * FROM users 
WHERE id IN (SELECT DISTINCT user_id FROM orders WHERE amount > 500);

-- 子查询(FROM中,即派生表)
SELECT t.username, t.avg_amount
FROM (
  SELECT u.id, u.username, AVG(o.amount) AS avg_amount
  FROM users u
  JOIN orders o ON u.id = o.user_id
  GROUP BY u.id, u.username
) t
WHERE t.avg_amount > 1000;

4.12. 高级查询技巧

-- CASE WHEN 条件判断(类似 if-else)
SELECT 
  username,
  age,
  CASE 
    WHEN age < 18 THEN '未成年'
    WHEN age BETWEEN 18 AND 60 THEN '成年'
    ELSE '老年'
  END AS age_group
FROM users;

-- 窗口函数(MySQL 8.0+,排名、累计等)
SELECT 
  username,
  salary,
  RANK() OVER (ORDER BY salary DESC) AS rank_salary,
  DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_rank,
  ROW_NUMBER() OVER (PARTITION BY status ORDER BY salary DESC) AS rn
FROM users;

-- 日期函数常用
SELECT 
  NOW() AS 当前时间,
  CURDATE() AS 当前日期,
  DATE_ADD(NOW(), INTERVAL 7 DAY) AS 一周后,
  DATEDIFF('2026-07-06', '2026-07-01') AS 相差天数,
  DATE_FORMAT(created_at, '%Y年%m月%d日 %H:%i:%s') AS 格式化时间
FROM users LIMIT 1;

4.13. 常用运维管理命令

-- 查看所有正在运行的连接/进程
SHOW PROCESSLIST;
-- 查完整版(包含SQL语句全文)
SHOW FULL PROCESSLIST;

-- 杀掉某个连接(线程ID)
KILL 12345;

-- 查看当前数据库所有表
SHOW TABLES;

-- 查看表状态(大小、行数等)
SHOW TABLE STATUS LIKE 'users'\G

-- 查看数据文件大小(MB)
SELECT 
  table_schema AS '数据库',
  table_name AS '表名',
  ROUND(((data_length + index_length) / 1024 / 1024), 2) AS '大小(MB)'
FROM information_schema.TABLES
WHERE table_schema = 'mydb'
ORDER BY (data_length + index_length) DESC;

-- 查看当前数据库连接数相关
SHOW VARIABLES LIKE 'max_connections';          -- 最大连接数设置
SHOW STATUS LIKE 'Threads_connected';           -- 当前连接数
SHOW STATUS LIKE 'Max_used_connections';        -- 历史最高连接数

-- 查看SQL执行状态(实时监控)
SHOW ENGINE INNODB STATUS\G                     -- InnoDB引擎状态

4.14. 实用组合场景示例

-- 场景1:查询最近7天注册、且有过至少1笔订单的用户
SELECT DISTINCT u.id, u.username, u.created_at
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
  AND o.order_time >= DATE_SUB(NOW(), INTERVAL 7 DAY);

-- 场景2:统计每个用户的订单总额,并按总额排序
SELECT 
  u.id,
  u.username,
  IFNULL(SUM(o.amount), 0) AS total_spent,
  COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.username
ORDER BY total_spent DESC;

-- 场景3:找出重复的邮箱
SELECT email, COUNT(*) AS cnt
FROM users
GROUP BY email
HAVING cnt > 1;

-- 场景4:插入数据,如果存在则忽略,如果不存在则插入(利用唯一键)
INSERT IGNORE INTO users (username, email, password_hash) 
VALUES ('newuser', 'new@example.com', 'hashxxx');

五、常见启动失败案例与排错

🔴 案例1:目录权限不足

错误日志
[ERROR] Could not open file '/data/mysql/mysql3306/logs/error.log' for error logging: Permission denied
原因/data/* 属主不是 mysql:mysql
解决

chown -R mysql:mysql /data/*

🔴 案例2:配置文件参数错误

错误日志
[ERROR] unknown variable 'basedi=/usr/local/mysql'(拼写错误)
原因:参数名写错或版本不支持
解决:检查配置文件,修正参数名(如 basedir)。


🔴 案例3:未指定正确配置文件

现象:启动时未使用 --defaults-file,或路径错误
排查

mysqld --verbose --help | grep defaults

解决:启动时务必带上 --defaults-file=/data/mysql/mysql3306/my3306.cnf


🔴 案例4:端口被占用

错误日志
[ERROR] Do you already have another mysqld server running on port: 3306 ?
原因:多实例端口冲突
解决:修改配置文件中的 port,或停止占用端口的进程。


🔴 案例5:误删二进制日志文件

错误日志
[ERROR] Failed to open log (file '/data/mysql/mysql3306/logs/mysql-bin.000014', errno 2)
解决:编辑 mysql-bin.index,删除对应行记录。


🔴 案例6:共享表空间大小不匹配

错误日志
[ERROR] InnoDB: The Auto-extending innodb_system data file './ibdata1' is of a different size ...
原因innodb_data_file_path 参数与现有 ibdata1 文件大小不一致
解决

  • 若在初始化前,修改参数为默认值(≤12M)
  • 若已初始化,需重新初始化(注意备份数据)。

六、启动失败通用排查方法

  1. 确认 MySQL 版本、启动方式及配置文件路径
  2. 查看错误日志(默认 error.log 路径在配置中指定)
    tail -100 /data/mysql/mysql3306/logs/error.log
    

七、数据库用户安全策略

7.1 初始化方式对比

选项 root 密码 密码存储位置
--initialize-insecure 空(无密码) 无需记录
--initialize 随机生成 error.log

7.2 修改 root 密码

-- 方法1:ALTER USER
ALTER USER root@'localhost' IDENTIFIED BY '123456';

-- 方法2:mysqladmin(命令行)
mysqladmin -uroot -p123456 password '123' -S /data/mysql/mysql3306/mysql.sock

7.3 清理无用用户

DELETE FROM mysql.user WHERE user != 'root';
FLUSH PRIVILEGES;

7.4 创建管理用户(示例)

-- 创建用户
CREATE USER ergou@'localhost' IDENTIFIED BY '123456';

-- 授予全部权限并允许转授权
GRANT ALL PRIVILEGES ON *.* TO ergou@'localhost' WITH GRANT OPTION;

附录:常用目录结构总览

/opt/mysql/mysql-8.0.20/          # 软件主目录
/usr/local/mysql -> /opt/mysql/... # 软链接
/data/mysql/mysql3306/
├── data/                          # 数据文件
├── logs/                          # 日志文件(error, binlog, slow)
└── my3306.cnf                     # 配置文件
posted @ 2026-07-06 21:24  DB哥  阅读(4)  评论(0)    收藏  举报