作为系统运维工程师,MySQL是绕不开的核心技能。本文将带你掌握MySQL运维的五大基础技能,从配置优化到日志分析,助你快速入门。
学习路线本文内容适合有Linux基础的运维新手,学习时长约3-5天。建议在测试环境中动手实践每个操作。
一、熟练配置my.cnf核心参数
MySQL的主配置文件my.cnf是性能调优的关键,掌握核心参数配置是运维的第一步。
1.1 配置文件位置
不同系统下my.cnf的默认位置:
# 查看MySQL读取配置文件的顺序mysql --help | grep my.cnf
# 常见位置ls -l /etc/my.cnf # CentOS/RHELls -l /etc/mysql/my.cnf # Ubuntu/Debianls -l ~/.my.cnf # 用户级配置配置优先级MySQL按顺序读取配置文件:
/etc/my.cnf→/etc/mysql/my.cnf→~/.my.cnf,后面的配置会覆盖前面的。
1.2 配置文件结构说明
my.cnf采用INI格式,由多个配置段组成:
[client] # 客户端程序(mysql命令)的配置参数名 = 参数值
[mysqld] # MySQL服务端的配置(最重要)参数名 = 参数值
[mysqldump] # mysqldump备份工具的配置参数名 = 参数值配置语法规则:
- 每行一个参数,格式为
参数名 = 参数值 #开头的行是注释- 参数名不区分大小写,但建议使用小写加下划线
- 数字单位
(千字节)、M(兆字节)、G(吉字节)
1.3 核心参数详解
下面是一份生产环境常用的my.cnf配置模板:
2 collapsed lines
[client]port = 3306socket = /var/lib/mysql/mysql.sock
[mysqld]# === 基本设置 ===port = 3306datadir = /var/lib/mysqlsocket = /var/lib/mysql/mysql.sockpid-file = /var/run/mysqld/mysqld.piduser = mysql
# === 字符集设置 ===character-set-server = utf8mb4collation-server = utf8mb4_unicode_ciinit_connect = 'SET NAMES utf8mb4'
# === 连接设置 ===max_connections = 500 # 最大连接数max_connect_errors = 100 # 最大连接错误数wait_timeout = 28800 # 空闲连接超时时间(秒)interactive_timeout = 28800back_log = 500 # 积压连接队列大小
# === 缓存设置 ===# InnoDB缓冲池大小,建议设置为物理内存的60-80%innodb_buffer_pool_size = 4Ginnodb_buffer_pool_instances = 4 # 多实例提高并发# 查询缓存(MySQL 8.0已移除)query_cache_size = 0
# === 日志设置 ===# 慢查询日志slow_query_log = 1slow_query_log_file = /var/log/mysql/slow.loglong_query_time = 2# 超过2秒的查询记录log_queries_not_using_indexes = 1 # 记录未使用索引的查询
# 错误日志log_error = /var/log/mysql/error.log
# 二进制日志(用于主从复制和数据恢复)log_bin = /var/log/mysql/mysql-binbinlog_format = ROWexpire_logs_days = 7 # 日志保留天数max_binlog_size = 100M # 单个日志文件大小
# === InnoDB设置 ===innodb_file_per_table = 1 # 每表独立表空间innodb_flush_log_at_trx_commit = 2 # 性能与安全平衡innodb_log_file_size = 256M # 事务日志大小innodb_log_buffer_size = 16M
# === 其他优化 ===tmp_table_size = 64Mmax_heap_table_size = 64Mtable_open_cache = 4000open_files_limit = 65535重点参数说明:
| 参数名 | 作用 | 推荐值 |
|---|---|---|
datadir | 数据文件存储目录 | /var/lib/mysql |
port | MySQL监听端口 | 3306(默认) |
max_connections | 允许的最大并发连接数 | 根据业务量调整,一般500-1000 |
innodb_buffer_pool_size | InnoDB缓存池大小 | 物理内存的60-80% |
character-set-server | 默认字符集 | utf8mb4(支持emoji) |
slow_query_log | 是否开启慢查询日志 | 1(开启) |
long_query_time | 慢查询阈值(秒) | 2(超过2秒记录) |
内存参数调优关键
innodb_buffer_pool_size是最重要的参数,建议设置为物理内存的60-80%。例如8GB内存的服务器可设置为5-6GB。
1.4 修改配置后重启服务
# 备份原配置cp /etc/my.cnf /etc/my.cnf.bak
# 编辑配置文件vim /etc/my.cnf
# 检查配置语法mysqld --validate-config
# 重启服务systemctl restart mysqld
# 检查服务状态systemctl status mysqld
# 验证参数是否生效mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"配置修改风险修改配置前务必备份原文件,错误的配置可能导致MySQL无法启动。建议在测试环境先验证。
二、掌握用户权限管理
MySQL的权限系统遵循最小权限原则,合理的权限管理是数据安全的基础。
2.1 用户创建语法详解
CREATE USER语法格式:
CREATE USER '用户名'@'允许登录的主机' IDENTIFIED BY '密码';语法组成部分:
用户名: 登录MySQL使用的账号名称@: 分隔符,固定写法允许登录的主机: 指定哪些机器可以用这个账号登录localhost: 只能本机登录192.168.1.100: 只能从这个IP登录192.168.1.%: 可以从192.168.1网段任意IP登录%: 可以从任意IP登录(不安全,生产环境慎用)
IDENTIFIED BY: 固定关键字,表示”密码是”密码: 登录时使用的密码,需要用单引号包裹
实际示例:
-- 创建只能本机登录的用户CREATE USER 'admin'@'localhost' IDENTIFIED BY 'Admin@2024';
-- 创建可以从192.168.1网段登录的用户CREATE USER 'webapp'@'192.168.1.%' IDENTIFIED BY 'StrongPass@2024';
-- 创建可以从任意IP登录的用户(测试环境)CREATE USER 'testuser'@'%' IDENTIFIED BY 'Test@2024';主机地址通配符
%: 匹配任意字符192.168.1.%: 匹配192.168.1.0到192.168.1.255%.example.com: 匹配example.com域下所有主机
2.2 权限授予语法详解
GRANT语法格式:
GRANT 权限类型 ON 数据库名.表名 TO '用户名'@'主机';语法组成部分:
权限类型: 要授予的权限,如SELECT、INSERT、UPDATE等ON: 固定关键字,表示”在…上”数据库名.表名: 指定权限作用范围*.*: 所有数据库的所有表webapp_db.*: webapp_db数据库的所有表webapp_db.users: webapp_db数据库的users表
TO: 固定关键字,表示”给”用户名@主机: 接收权限的用户
实际示例:
-- 授予webapp_db数据库的所有权限GRANT ALL PRIVILEGES ON webapp_db.* TO 'webapp'@'192.168.1.%';
-- 授予只读权限(只能查询)GRANT SELECT ON webapp_db.* TO 'readonly'@'%';
-- 授予特定表的增删改查权限GRANT SELECT, INSERT, UPDATE, DELETE ON webapp_db.users TO 'app'@'%';
-- 授予所有数据库的查询权限GRANT SELECT ON *.* TO 'monitor'@'localhost';
-- 刷新权限(使授权立即生效)FLUSH PRIVILEGES;常用权限类型说明:
| 权限名称 | 说明 | 对应操作 |
|---|---|---|
SELECT | 查询数据 | SELECT * FROM table |
INSERT | 插入数据 | INSERT INTO table VALUES(...) |
UPDATE | 更新数据 | UPDATE table SET ... |
DELETE | 删除数据 | DELETE FROM table |
CREATE | 创建数据库/表 | CREATE DATABASE/TABLE |
DROP | 删除数据库/表 | DROP DATABASE/TABLE |
ALTER | 修改表结构 | ALTER TABLE |
INDEX | 创建/删除索引 | CREATE INDEX |
ALL PRIVILEGES | 所有权限(除GRANT) | 上述所有操作 |
GRANT OPTION | 授权给其他用户 | GRANT ... TO ... |
2.3 完整的用户创建与授权流程
-- 第1步:创建用户CREATE USER 'webapp'@'192.168.1.%' IDENTIFIED BY 'StrongPass@2024';
-- 第2步:授予权限GRANT SELECT, INSERT, UPDATE, DELETE ON webapp_db.* TO 'webapp'@'192.168.1.%';
-- 第3步:刷新权限FLUSH PRIVILEGES;
-- 第4步:查看用户权限SHOW GRANTS FOR 'webapp'@'192.168.1.%';
-- 第5步:测试登录-- 在应用服务器上执行:-- mysql -h 数据库服务器IP -u webapp -p为什么要分开创建用户和授权?MySQL将用户管理和权限管理分离:
CREATE USER: 创建登录凭证(用户名+密码+允许登录的主机)GRANT: 授予这个用户可以做什么操作 这样设计更灵活,可以随时调整用户权限而不影响登录凭证。
2.4 不同场景的权限配置
-- 场景1:应用程序账号(读写权限,不能改表结构)CREATE USER 'app_user'@'10.0.0.%' IDENTIFIED BY 'AppPass@2024';GRANT SELECT, INSERT, UPDATE, DELETEON webapp_db.*TO 'app_user'@'10.0.0.%';
-- 场景2:备份账号(需要锁表权限)CREATE USER 'backup_user'@'localhost' IDENTIFIED BY 'BackupPass@2024';GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGERON *.*TO 'backup_user'@'localhost';
-- 场景3:监控账号(仅需查看权限)CREATE USER 'monitor'@'%' IDENTIFIED BY 'MonitorPass@2024';GRANT SELECT, PROCESS, REPLICATION CLIENTON *.*TO 'monitor'@'%';
-- 场景4:开发测试账号(开发库全部权限)CREATE USER 'developer'@'%' IDENTIFIED BY 'DevPass@2024';GRANT ALL PRIVILEGESON dev_db.*TO 'developer'@'%';
-- 统一刷新权限FLUSH PRIVILEGES;2.5 用户管理进阶操作
查看用户语法:
-- 查看所有用户SELECT user, host, account_locked FROM mysql.user;
-- 查看当前登录用户SELECT USER(), CURRENT_USER();
-- 查看指定用户的权限SHOW GRANTS FOR 'webapp'@'192.168.1.%';修改密码语法:
ALTER USER '用户名'@'主机' IDENTIFIED BY '新密码';-- 修改webapp用户的密码ALTER USER 'webapp'@'192.168.1.%' IDENTIFIED BY 'NewPass@2024';
-- 修改当前登录用户自己的密码ALTER USER USER() IDENTIFIED BY 'MyNewPass@2024';撤销权限语法:
REVOKE 权限类型 ON 数据库名.表名 FROM '用户名'@'主机';-- 撤销DELETE权限REVOKE DELETE ON webapp_db.* FROM 'webapp'@'192.168.1.%';
-- 撤销所有权限REVOKE ALL PRIVILEGES ON webapp_db.* FROM 'webapp'@'192.168.1.%';
-- 刷新权限FLUSH PRIVILEGES;删除用户语法:
DROP USER '用户名'@'主机';-- 删除指定用户DROP USER 'olduser'@'%';
-- 删除多个用户DROP USER 'user1'@'%', 'user2'@'localhost';锁定/解锁用户:
-- 锁定用户(禁止登录)ALTER USER 'webapp'@'192.168.1.%' ACCOUNT LOCK;
-- 解锁用户ALTER USER 'webapp'@'192.168.1.%' ACCOUNT UNLOCK;删除用户注意事项删除用户会同时删除该用户的所有权限,但不会删除该用户创建的数据库和表。删除前请确认:
- 该用户不再被应用程序使用
- 已备份相关数据
- 已通知相关人员
三、掌握数据库、表、数据的基本操作
这是运维日常工作中最频繁的操作,必须熟练掌握。
3.1 数据库操作
查看数据库语法:
SHOW DATABASES;-- 查看所有数据库SHOW DATABASES;
-- 查看数据库名包含"app"的数据库SHOW DATABASES LIKE '%app%';创建数据库语法:
CREATE DATABASE 数据库名 CHARACTER SET 字符集 COLLATE 排序规则;语法说明:
数据库名: 要创建的数据库名称,建议使用小写字母和下划线CHARACTER SET: 指定字符集,推荐utf8mb4(支持emoji和特殊字符)COLLATE: 指定排序规则,推荐utf8mb4_unicode_ci(不区分大小写)
-- 创建数据库(指定字符集)CREATE DATABASE webapp_dbCHARACTER SET utf8mb4COLLATE utf8mb4_unicode_ci;
-- 创建数据库(简化写法,使用默认字符集)CREATE DATABASE test_db;
-- 如果数据库不存在才创建CREATE DATABASE IF NOT EXISTS webapp_db;查看数据库详情:
-- 查看数据库创建语句SHOW CREATE DATABASE webapp_db;
-- 查看数据库字符集SELECT SCHEMA_NAME AS '数据库名', DEFAULT_CHARACTER_SET_NAME AS '字符集', DEFAULT_COLLATION_NAME AS '排序规则'FROM information_schema.SCHEMATAWHERE SCHEMA_NAME = 'webapp_db';切换数据库语法:
USE 数据库名;-- 切换到webapp_db数据库USE webapp_db;
-- 查看当前使用的数据库SELECT DATABASE();删除数据库语法:
DROP DATABASE 数据库名;-- 删除数据库(危险操作!)DROP DATABASE test_db;
-- 如果数据库存在才删除DROP DATABASE IF EXISTS test_db;删除数据库风险
DROP DATABASE会永久删除数据库及其所有表和数据,无法恢复!生产环境操作前必须:
- 确认数据库不再使用
- 完成数据备份
- 获得上级审批
3.2 数据表操作
创建表语法:
CREATE TABLE 表名 ( 字段名1 数据类型 [约束], 字段名2 数据类型 [约束], ... [索引定义]) ENGINE=存储引擎 DEFAULT CHARSET=字符集 COMMENT='表注释';常用数据类型:
| 数据类型 | 说明 | 示例 |
|---|---|---|
INT | 整数 | 用户ID、年龄 |
BIGINT | 大整数 | 订单号、手机号 |
VARCHAR(长度) | 可变长度字符串 | 用户名、邮箱 |
TEXT | 长文本 | 文章内容、备注 |
DECIMAL(总位数,小数位) | 精确小数 | 金额、价格 |
DATE | 日期 | 生日(2024-01-01) |
DATETIME | 日期时间 | 创建时间(2024-01-01 10:30:00) |
TIMESTAMP | 时间戳 | 更新时间(自动记录) |
TINYINT | 小整数 | 状态(0/1)、性别 |
常用约束:
| 约束 | 说明 | 示例 |
|---|---|---|
PRIMARY KEY | 主键(唯一且非空) | id INT PRIMARY KEY |
AUTO_INCREMENT | 自动递增 | id INT AUTO_INCREMENT |
NOT NULL | 不允许为空 | username VARCHAR(50) NOT NULL |
UNIQUE | 唯一(不能重复) | email VARCHAR(100) UNIQUE |
DEFAULT | 默认值 | status TINYINT DEFAULT 1 |
COMMENT | 字段注释 | username VARCHAR(50) COMMENT '用户名' |
-- 创建用户表CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID', username VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名', email VARCHAR(100) COMMENT '邮箱', password VARCHAR(255) NOT NULL COMMENT '密码', status TINYINT DEFAULT 1 COMMENT '状态:1启用 0禁用', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', INDEX idx_username (username), INDEX idx_email (email)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
-- 创建订单表CREATE TABLE orders ( id BIGINT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL UNIQUE COMMENT '订单号', user_id INT NOT NULL COMMENT '用户ID', total DECIMAL(10,2) NOT NULL COMMENT '订单金额', status TINYINT DEFAULT 0 COMMENT '状态:0待付款 1已付款 2已发货 3已完成', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_user_id (user_id), INDEX idx_order_no (order_no), INDEX idx_status (status)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';为什么要加索引?索引就像书的目录,可以快速找到数据:
- 在经常用于查询条件的字段上建索引(如
WHERE username = 'xxx')- 在经常用于排序的字段上建索引(如
ORDER BY created_at)- 在经常用于关联的字段上建索引(如
JOIN ON user_id)
查看表结构语法:
-- 查看表结构(简洁)DESC users;
-- 查看表结构(详细)SHOW COLUMNS FROM users;
-- 查看建表语句SHOW CREATE TABLE users;
-- 查看表索引SHOW INDEX FROM users;
-- 查看表状态(大小、行数等)SHOW TABLE STATUS LIKE 'users';修改表结构语法:
-- 添加字段ALTER TABLE 表名 ADD COLUMN 字段名 数据类型 [约束];
-- 修改字段ALTER TABLE 表名 MODIFY COLUMN 字段名 新数据类型;
-- 删除字段ALTER TABLE 表名 DROP COLUMN 字段名;
-- 添加索引ALTER TABLE 表名 ADD INDEX 索引名 (字段名);
-- 删除索引ALTER TABLE 表名 DROP INDEX 索引名;-- 添加手机号字段ALTER TABLE users ADD COLUMN phone VARCHAR(20) COMMENT '手机号';
-- 修改邮箱字段长度ALTER TABLE users MODIFY COLUMN email VARCHAR(150);
-- 删除手机号字段ALTER TABLE users DROP COLUMN phone;
-- 在status字段上添加索引ALTER TABLE users ADD INDEX idx_status (status);
-- 删除索引ALTER TABLE users DROP INDEX idx_status;
-- 修改表名ALTER TABLE users RENAME TO sys_users;查看表占用空间:
-- 查看指定数据库所有表的大小SELECT table_name AS '表名',ROUND((data_length + index_length) / 1024 / 1024, 2) AS '大小(MB)', table_rows AS '行数'FROM information_schema.tablesWHERE table_schema = 'webapp_db'ORDER BY (data_length + index_length) DESC;删除表语法:
-- 删除表(删除表结构和数据)DROP TABLE users;
-- 如果表存在才删除DROP TABLE IF EXISTS users;
-- 清空表数据(保留表结构,重置自增ID)TRUNCATE TABLE users;
-- 删除表数据(保留表结构,不重置自增ID)DELETE FROM users;TRUNCATE vs DELETE
TRUNCATE TABLE: 快速清空表,重置自增ID,不能回滚DELETE FROM: 逐行删除,不重置自增ID,可以回滚 生产环境清空大表推荐用TRUNCATE,速度更快。
3.3 数据操作(CRUD)
INSERT - 插入数据语法:
INSERT INTO 表名 (字段1, 字段2, ...) VALUES (值1, 值2, ...);-- 插入单条数据INSERT INTO users (username, email, password)VALUES ('admin', 'admin@example.com', 'hashed_password');
-- 插入数据(省略字段名,按表结构顺序)INSERT INTO usersVALUES (NULL, 'user1', 'user1@example.com', 'pass1', 1, NOW(), NOW());
-- 批量插入(推荐,效率高)INSERT INTO users (username, email, password) VALUES('user1', 'user1@example.com', 'pass1'),('user2', 'user2@example.com', 'pass2'),('user3', 'user3@example.com', 'pass3');
-- 插入时忽略重复数据(不报错)INSERT IGNORE INTO users (username, email, password)VALUES ('admin', 'admin@example.com', 'pass');
-- 插入或更新(如果主键/唯一键冲突则更新)INSERT INTO users (id, username, email, password)VALUES (1, 'admin', 'admin@example.com', 'newpass')ON DUPLICATE KEY UPDATE email = 'admin@example.com', password = 'newpass';SELECT - 查询数据语法:
SELECT 字段列表 FROM 表名 [WHERE 条件] [ORDER BY 排序] [LIMIT 数量];-- 查询所有数据SELECT * FROM users;
-- 查询指定字段SELECT id, username, email FROM users;
-- 条件查询SELECT * FROM users WHERE status = 1;
-- 多条件查询(AND表示"并且")SELECT * FROM users WHERE status = 1 AND created_at >= '2024-01-01';
-- 多条件查询(OR表示"或者")SELECT * FROM users WHERE username = 'admin' OR email = 'admin@example.com';
-- 模糊查询(LIKE)SELECT * FROM users WHERE email LIKE '%@gmail.com';
-- 范围查询(BETWEEN)SELECT * FROM users WHERE id BETWEEN 10 AND 100;
-- 列表查询(IN)SELECT * FROM users WHERE id IN (1, 5, 10, 20);
-- 空值查询SELECT * FROM users WHERE email IS NULL;
-- 非空查询SELECT * FROM users WHERE email IS NOT NULL;
-- 排序查询(ASC升序,DESC降序)SELECT * FROM users ORDER BY created_at DESC;
-- 限制返回数量SELECT * FROM users LIMIT 10;
-- 分页查询(跳过前10条,取10条)SELECT * FROM users LIMIT 10, 10;
-- 去重查询SELECT DISTINCT username FROM users;
-- 统计查询SELECT COUNT(*) AS total FROM users;SELECT COUNT(*) AS total FROM users