SQL与MySQL

介绍sql与mysql理论知识

发布于 作者 Shifenmiao更新于 技术0

1. 数据库与表结构管理(DDL)

SQL 语句 解释与使用场景
SHOW DATABASES; 列出当前 MySQL 实例中所有数据库。运维时用于查看实例上有哪些库,确认备份/迁移范围。
CREATE DATABASE testdb CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; 创建名为 testdb 的数据库,指定字符集为 utf8mb4(支持 emoji 和特殊字符),排序规则为通用不区分大小写。测试时需要快速搭建同构环境。
DROP DATABASE testdb; 删除整个数据库(危险操作)。测试后清理环境时使用,不可逆。
USE testdb; 切换到 testdb 数据库,后续操作默认在该库上执行。
SHOW TABLES; 查看当前库下所有表。确认表是否创建成功或排查表丢失问题。
SHOW CREATE TABLE user\G 显示建表时的完整 DDL,包括引擎、字符集、索引、注释等。\G 表示纵向显示,阅读更清晰。常用于迁移表结构或排查表定义差异。
DESC user; 等价于DESCRIBE user,展示列名、类型、是否允许空、键信息等。快速查看表结构。
CREATE TABLE t (id INT PRIMARY KEY AUTO_INCREMENT, ...) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 创建表,定义 id 为主键自增,指定 InnoDB 引擎和 utf8mb4 编码。InnoDB 支持事务,是生产主流。
ALTER TABLE t ADD COLUMN age TINYINT AFTER name; 在 name 列后新增 age 列,类型 TINYINT。注意大表添加列会锁表(视版本和算法而定),测试时应了解其影响。
ALTER TABLE t MODIFY COLUMN name VARCHAR(100); 修改 name 列类型或约束。可能引起锁表和数据重建,需谨慎。
ALTER TABLE t DROP COLUMN age; 删除 age 列,同样有性能风险,生产操作应避开高峰期。
RENAME TABLE t TO t_new; 表重命名,原子操作,不影响数据。运维时用于归档旧表或表切换。
TRUNCATE TABLE t; 清空表所有数据并重置自增计数器,不可回滚(DDL 隐式提交)。比 DELETE 快,但测试时注意它无法触发触发器。
DROP TABLE IF EXISTS t; 如果表存在则删除。谨慎操作,数据无法恢复。

2. 索引管理

SQL 语句 解释
SHOW INDEX FROM table_name; 查看表上所有索引的名称、列、唯一性、基数等,帮助分析索引使用情况。
ALTER TABLE t ADD INDEX idx_name (name); 创建普通索引,加快基于 name 的等值或范围查询。索引会占用额外空间并影响写入速度。
ALTER TABLE t ADD UNIQUE idx_email (email); 唯一索引,确保 email 值不重复,同时加速查询。测试中常用于验证唯一约束的正确性。
ALTER TABLE t ADD PRIMARY KEY (id); 定义主键,InnoDB 会根据主键构建聚集索引,表数据按主键顺序存储。没有主键时会创建隐藏的 row_id,不建议依赖。
ALTER TABLE t ADD INDEX idx_multi (col1, col2); 联合索引,遵循最左前缀原则。例如查询 where col1=? 可以用上,但直接查 col2=? 不能有效使用。
ALTER TABLE t DROP INDEX idx_name; 删除指定索引,减少写入负担,但要评估查询影响。
SELECT * FROM t FORCE INDEX (idx_name) WHERE name='test'; 强制优化器使用指定索引,用于测试索引性能对比或优化器选错索引时的临时修复。

3. 用户与权限管理(DCL)

SQL 语句 解释
SELECT user,host FROM mysql.user; 查看 MySQL 全局用户账号及允许连接的主机。host 为 % 表示允许任何主机连接。
CREATE USER 'appuser'@'%' IDENTIFIED BY 'StrongPass123!'; 创建可从任意主机登录的用户,密码需符合密码策略。测试常需要创建不同权限的账号验证访问控制。
GRANT ALL PRIVILEGES ON testdb.* TO 'appuser'@'%'; 将 testdb 库所有对象的所有权限赋予 appuser。权限粒度可以是库、表、列。
GRANT SELECT ON testdb.* TO 'readonly'@'192.168.1.%'; 仅授予 SELECT 权限,限制来源 IP 段,符合最小权限原则。
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'%'; 创建复制专用账号,赋予从库复制所必需的权限。
REVOKE DELETE ON testdb.* FROM 'appuser'@'%'; 回收特定权限,立即生效,但该用户已建立的连接不会受影响。
FLUSH PRIVILEGES; 重新加载授权表。直接 DML 操作权限表后必须执行,但用 GRANT/REVOKE 时通常自动生效。
DROP USER 'readonly'@'192.168.1.%'; 删除用户,同时清理其所有权限。

4. 数据查询与分析(DQL)

SQL 语句 解释
SELECT * FROM t WHERE id > 100 LIMIT 10; 条件分页查询,LIMIT 限制返回行数,测试可用来小范围验证数据。
SELECT COUNT(*), MAX(score), AVG(score) FROM t GROUP BY class; 聚合查询,按班级统计人数、最高分和平均分。常用于报表和校验数据。
SELECT TABLE_NAME, TABLE_ROWS FROM information_schema.TABLES WHERE TABLE_SCHEMA='testdb'; 从信息模式表中获取每张表的估算行数(非精确,但可快速掌握数据量级),用于制定备份策略或估算测试时间。
SELECT email, COUNT(*) FROM user GROUP BY email HAVING COUNT(*)>1; 查找重复的 email 记录,HAVING 对聚合结果过滤,测试数据质量校验常用。
SELECT * FROM large_table ORDER BY RAND() LIMIT 100; 随机取 100 条,全表排序产生临时表,极慢,仅适合极小表。测试性能时要避免。
SELECT * FROM large_table WHERE id >= (SELECT FLOOR(MAX(id)*RAND()) FROM large_table) LIMIT 100; 随机抽样改进版,利用主键范围随机起点,效率高,适合测试环境快速取样本。
SELECT GROUP_CONCAT(id) FROM t WHERE status=1; 将多个 id 拼接成一个字符串,默认用逗号分隔,方便导出数据清单或构造 IN 列表。
SELECT name, score, ROW_NUMBER() OVER (PARTITION BY class ORDER BY score DESC) AS rank FROM student; 窗口函数(8.0+),按班级分组内排名,不折叠行,比 GROUP BY 灵活,测试中用于分析排名和数据分布。

5. 数据操作与事务(DML)

SQL 语句 解释
INSERT INTO t (name, age) VALUES ('test', 25), ('demo', 30); 批量插入,减少网络往返。测试时用于快速生成基础数据。
INSERT INTO t SELECT * FROM backup_t WHERE create_date < '2025-01-01'; 将查询结果直接插入目标表,用于数据迁移或备份恢复。注意列顺序和类型匹配。
UPDATE t SET status=0 WHERE id IN (1,2,3); 条件更新,IN 列表适合少量明确记录。大批量更新需分批进行,避免锁表。
DELETE FROM t WHERE expire_time < NOW(); 根据条件删除过期数据。生产需注意一次性删除大量行会占用锁和 undo 表空间。
START TRANSACTION; UPDATE ...; COMMIT; 显式事务,所有操作作为一个原子单元。测试中用来模拟事务性操作和验证 ACID。
ROLLBACK; 回滚事务,撤销所有未提交更改。常用于测试异常场景和回滚段压力。
SELECT * FROM information_schema.INNODB_TRX; 查看当前活跃的 InnoDB 事务,包括事务 ID、状态、持续时间等,协助排查长事务锁问题。

6. 性能诊断与监控

SQL 语句 解释
SHOW PROCESSLIST; 列出所有前端连接及其当前执行的 SQL 和执行状态。发现慢查询、锁等待、连接数异常时首先使用。
KILL 123; 杀掉 ID 为 123 的连接,用于终止异常查询或释放锁。KILL 不保证立即终止,可能需要 KILL QUERY 然后 KILL CONNECTION。
EXPLAIN SELECT * FROM t WHERE name='test'; 查看执行计划,包括访问方式、使用索引、扫描行数等。是 SQL 优化的核心工具。
EXPLAIN FORMAT=JSON SELECT ...; 输出 JSON 格式的执行计划,包含成本信息,更精细。
EXPLAIN ANALYZE SELECT ...; (MySQL 8.0.18+) 实际执行 SQL 并返回每步的实际时间和行数,用于验证优化器估算的准确性。
SHOW VARIABLES LIKE 'slow_query%'; 检查慢查询日志相关设置:是否开启、日志文件路径。
SHOW VARIABLES LIKE 'long_query_time'; 慢查询时间阈值,超过该值的 SQL 会被记录。
SELECT * FROM mysql.slow_log LIMIT 10; 当启用表输出(log_output=TABLE)时,可直接查询慢 SQL 记录。
SELECT * FROM information_schema.INNODB_LOCKS; 查看当前 InnoDB 锁等待信息(5.7 可用,8.0 用performance_schema.data_locks)。
SELECT * FROM information_schema.INNODB_LOCK_WAITS; 展示哪个事务被哪个事务阻塞,用于死锁排查。
SELECT table_name, data_length, index_length, data_free FROM information_schema.TABLES WHERE table_schema='testdb'; 查看表的数据大小、索引大小及碎片空间,data_free 过大时可考虑 OPTIMIZE TABLE 回收。
SELECT @@transaction_isolation; 查看当前会话的事务隔离级别,确认环境配置。
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; 动态修改会话隔离级别,常用于临时满足特定业务需求或测试不同隔离级别的行为。

7. 备份与恢复相关 SQL

命令/SQL 解释
mysqldump -u root -p --no-data testdb > schema.sql 仅导出建表结构,不含数据。用于搭建相同表结构的测试环境或版本控制。
mysqldump -u root -p testdb table1 table2 > data.sql 导出指定表的结构+数据,常用于单表恢复或迁移。
mysqldump ... --single-transaction --master-data=2 事务一致性备份,不锁表,并记录 binlog 位置(master-data=2 输出为注释),为搭建从库或时间点恢复提供起点。
SELECT * INTO OUTFILE '/tmp/user.csv' FIELDS TERMINATED BY ',' FROM user; 将查询结果导出为 CSV 文件。需确保 MySQL 有目录写入权限,安全参数secure_file_priv 不限制此路径。
LOAD DATA INFILE '/tmp/user.csv' INTO TABLE user FIELDS TERMINATED BY ','; 从文件快速批量导入数据,性能远高于逐条 INSERT,测试大量数据装载必用。
mysql -u root -p testdb < backup.sql 执行 SQL 文件进行恢复。注意可能需要临时调大max_allowed_packet。

8. 系统状态与变量

SQL 语句 解释
SHOW GLOBAL STATUS LIKE 'Threads_connected'; 当前打开的连接数,反映并发量。对比max_connections 评估连接使用率。
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool%'; 查看缓冲池命中率等相关状态,Innodb_buffer_pool_read_requests 与 reads 的比值即命中率,过低需调大 buffer pool。
SHOW VARIABLES LIKE 'max_connections'; 查看最大允许连接数。若Threads_connected 接近此值,客户端会报连接拒绝。
SHOW VARIABLES LIKE '%innodb%'; 查看所有 InnoDB 相关配置,如日志文件大小、刷新策略、IO 线程数等。
SHOW VARIABLES LIKE 'binlog%'; 查看二进制日志配置,如是否开启、格式、过期时间等,对复制和恢复至关重要。
SET GLOBAL max_connections = 500; 在线动态调大连接上限,无需重启。但需评估系统承受能力。

9. 主从复制运维

SQL 语句 解释
SHOW SLAVE STATUS\G 查看从库复制状态:IO/SQL 线程运行状态、主库信息、延迟秒数、错误信息等。运维最常用。
START SLAVE; / STOP SLAVE; 启动/停止复制线程。维护时可能需要临时停止,注意延迟会累积。
RESET SLAVE ALL; 清除所有从库配置信息,彻底断开复制关系。切换主库或重建从库时执行。
SHOW MASTER STATUS; 查看当前主库的 binlog 文件名和位置,配置从库或增量备份时需要。
SHOW BINARY LOGS; 列出所有 binlog 文件及其大小,用于判断日志保留策略和磁盘占用。
SHOW BINLOG EVENTS IN 'mysql-bin.000001' LIMIT 10; 查看 binlog 中的具体事件,用于解析数据变更、排查问题或验证复制故障。

二、MySQL 理论知识逐条详解

1. 体系架构

MySQL 分为四层:

  • 连接层:处理客户端连接、用户认证,每个连接分配一个线程(线程池可复用),半双工协议。
  • 服务层:核心大脑。SQL 接口、解析器(语法分析)、查询优化器(选择索引、join 顺序)、查询缓存(8.0 已移除)、内置函数(日期、数学等)。所有引擎共享此层。
  • 引擎层:可插拔存储引擎,负责数据实际的存储和读取。InnoDB 是最主要的事务引擎。
  • 存储层:物理文件系统,包括 .ibd(表空间)、redo log、undo log、binlog、错误日志等。

测试运维意义:了解架构能快速定位问题(是 SQL 解析慢还是引擎 I/O 瓶颈),理解缓存和日志的交互。

2. 存储引擎对比

特性 InnoDB MyISAM
事务 支持 ACID,通过 undo/redo 实现 不支持
锁粒度 行级锁(通过索引实现)、间隙锁 表级锁
外键 支持 不支持
崩溃恢复 基于 redo log 自动恢复 依赖修复工具,易损坏
存储结构 表空间(共享或独立),数据和索引按主键聚集 数据文件.MYD 和索引文件 .MYI 分离
适用 高并发 OLTP、核心业务 只读历史表、日志表(无事务要求)

现代测试环境:默认使用 InnoDB,MyISAM 仅用于对比锁行为或临时表。

3. 索引原理

  • B+Tree 结构:所有数据存储于叶子节点,非叶子节点只存导航键。叶子节点有序且包含完整数据或主键值,支持范围扫描。
  • 聚集索引:InnoDB 以主键构建 B+Tree,叶子节点包含整行数据。因此主键插入应使用有序递增 ID,避免随机主键导致页分裂。
  • 辅助索引:非主键索引的叶子节点存主键值,查询需要回表(二次查找聚集索引)。覆盖索引可避免回表。
  • 联合索引最左前缀:索引 (a,b,c) 相当于创建了 a, a,b, a,b,c 三个索引,查询条件中缺少 a 时该索引用不上。
  • 覆盖索引 (Covering Index):查询所需列全部包含在索引中,EXPLAIN 的 Extra 列会显示 Using index,性能最佳。
  • 索引下推 (ICP):存储引擎层利用索引中的列提前过滤掉不满足 WHERE 条件的记录,减少回表次数。EXPLAIN 显示 Using index condition。
  • 索引失效场景:
    • LIKE '%abc' 开头模糊
    • 在索引列上使用函数 WHERE UPPER(name)='A'
    • 隐式类型转换 WHERE phone=13800138000(phone 是 varchar 时走不上索引)
    • OR 条件中有一边无索引

测试必备:构造不同查询验证索引使用,分析执行计划,对比性能。

4. 事务与隔离级别

  • ACID:
    • 原子性:通过 undo log 回滚实现。
    • 持久性:通过 redo log 保障,即使崩溃后也能重做。
    • 隔离性:MVCC + 锁机制实现并发事务互不干扰。
    • 一致性:由以上三者共同保障,同时业务逻辑约束(外键、触发器等)维护。
  • 四种隔离级别:
    1. READ UNCOMMITTED:可能读到未提交的数据(脏读),基本不用于生产。
    2. READ COMMITTED:每次查询都重建 ReadView,只能读到已提交的数据,解决脏读,但存在不可重复读(同一事务两次读取结果不同)。
    3. REPEATABLE READ (默认):事务首次查询时创建 ReadView,整个事务使用同一快照,避免不可重复读。通过间隙锁/Next-Key Lock 进一步减少幻读。
    4. SERIALIZABLE:所有 SELECT 隐式变为 LOCK IN SHARE MODE,全串行化,并发最低。
  • MVCC 机制:每行记录有隐藏的 DB_TRX_ID(最近修改事务ID)和 DB_ROLL_PTR(回滚指针指向 undo 记录)。通过比较事务 ID 和 ReadView 确定数据可见性。
  • ReadView 可见性算法:包含活跃事务列表,若行记录的 DB_TRX_ID 小于最小活跃事务 ID,则可见;若大于等于下一个分配的事务 ID,则不可见(需要回查 undo 链)。

测试常见:模拟并发更新,验证幻读、不可重复读行为,理解 RR 级别下“快照读”与“当前读”的区别。

5. 锁机制

  • 表锁:直接锁定整张表,实现简单但并发低,MyISAM 及部分 DDL 使用。
  • 行锁(Record Lock):精确锁定索引记录,只有通过索引条件检索时 InnoDB 才会使用行锁,否则退化为表锁。
  • 共享锁(S)和排他锁(X):S 锁允许其他事务加 S 但不允许加 X;X 锁排斥一切其他锁。
  • 意向锁(IS/IX):表级锁,表明事务有意在行上加 S 或 X 锁,用于快速判断表级冲突,不阻塞行锁。
  • 间隙锁(Gap Lock):锁定索引记录之间的间隙,防止其他事务插入记录,是 RR 隔离级别下防幻读的手段。
  • Next-Key Lock:记录锁 + 间隙锁的组合,锁定一个左开右闭区间。
  • 死锁:两个事务互相等待对方持有的锁,形成循环等待。InnoDB 自动检测,回滚代价较小的事务(影响行数少)。SHOW ENGINE INNODB STATUS 查看死锁详情。
  • 排查锁问题:通过 information_schema 的锁相关表或 sys.schema_table_lock_waits(8.0)识别阻塞者和被阻塞者。

运维测试:压测时观察锁等待率、死锁频率,优化事务顺序和索引设计。

6. 日志系统

  • binlog(二进制日志):Server 层产生,记录数据库所有修改事件(DDL/DML),用于复制和时间点恢复。格式有 STATEMENT(记录SQL)、ROW(记录行变更,更安全)、MIXED。
  • redo log:InnoDB 物理日志,循环写入两组固定大小文件,记录“数据页的物理修改”。保证事务持久性,崩溃恢复时利用 redo log 重做已提交事务。
  • undo log:逻辑日志,记录变更前的数据版本,用于事务回滚和 MVCC 构建历史版本。存放在 undo 表空间。
  • error log:记录启动、运行、关闭过程中的重要错误和告警。排查服务起不来、崩溃等问题的第一入口。
  • slow query log:记录执行时间超过 long_query_time 的 SQL,可以通过 log_output 输出到文件或表,是 SQL 优化的主要来源。
  • general log:记录所有客户端连接和 SQL 请求,极度消耗性能,仅用于短暂调试,生产不可开启。

测试关注:redo log 大小和刷盘策略(innodb_flush_log_at_trx_commit)影响写入性能;binlog 格式影响恢复和复制。

7. SQL 优化流程

  1. 发现慢 SQL:开启慢查询日志或通过监控工具(如 Prometheus + mysqld_exporter)。
  2. 分析执行计划:使用 EXPLAIN,重点关注:
    • type:连接类型,从优到差 system > const > eq_ref > ref > range > index > ALL。
    • key:实际使用的索引。
    • rows:优化器估算需要扫描的行数。
    • Extra:Using filesort(需要额外排序)和 Using temporary(使用临时表)通常需要优化。
  3. 优化手段:
    • 创建合适索引:优先考虑高选择性列,联合索引注意最左前缀。
    • 改写 SQL:避免 SELECT *,只取需要的列;分页用延迟关联;用 JOIN 替代子查询(视情况)。
    • 表结构优化:使用合适的数据类型,减少行大小,提高缓冲池利用率。
    • 参数调优:增大 join_buffer_size,调整 sort_buffer_size 等。
  4. 大表处理:考虑分区(按时间范围等),或通过中间件进行水平分库分表。

测试流程:构造不同数据量级,压测优化前后的 SQL,量化提升效果。

8. 主从复制与高可用

  • 复制原理:
    • 主库:事务提交时写入 binlog,binlog dump 线程将日志推送给从库 I/O 线程。
    • 从库:I/O 线程接收日志写入 relay log,SQL 线程重放 relay log 中的事件。
  • 异步复制:主库提交后不等待从库确认,从库可能延迟甚至丢失数据。性能最高。
  • 半同步复制:主库等待至少一个从库将 binlog 写入 relay log(并刷盘)才返回客户端,保证数据至少存在于一台从库,降低丢失风险。
  • GTID 复制:每个事务分配全局唯一 GTID,简化故障切换时的位置定位,CHANGE MASTER TO MASTER_AUTO_POSITION=1 即可自动对齐。
  • 并行复制:从库 SQL 线程可以并行回放不同库或不同组事务(基于逻辑时钟),大幅减少延迟。

运维测试:模拟主库宕机,验证从库提升流程和数据一致性;压测时观察复制延迟。

9. 备份与恢复策略

  • 逻辑备份(mysqldump/mydumper):导出为 SQL 文件,可读可编辑,跨版本迁移方便,但速度慢,大库恢复时间长达数小时。
  • 物理备份(Xtrabackup/MySQL Enterprise Backup):直接拷贝 InnoDB 数据文件并记录 redo log 增量,支持在线热备不阻塞业务,恢复速度接近文件拷贝,是生产首选。
  • 时间点恢复(PITR):恢复流程为“全量备份恢复 + 从全备后的 binlog 重放到指定时间点”。基于 GTID 或时间点位置 mysqlbinlog 工具进行解析。

测试必须:定期全备+增备演练,记录备份和恢复耗时,确保 RPO/RTO 达标。

10. 重要参数与调优方向

  • 连接:
    • max_connections:最大连接数,过大会消耗内存。
    • back_log:等待连接队列长度。
    • thread_cache_size:线程缓存数,减少频繁创建销毁开销。
  • InnoDB 缓冲池:
    • innodb_buffer_pool_size:核心内存区域,缓存数据页和索引页,建议设置为物理内存的 50%~80%。命中率过低会频繁磁盘 I/O。
  • 日志:
    • innodb_log_file_size:redo log 单个文件大小,过小会导致频繁 checkpoint 刷脏页,影响写入性能;过大恢复时间长。
    • innodb_flush_log_at_trx_commit:
      • 1:每次提交刷 redo log,最安全。
      • 2:每次提交写 OS 缓存但不立刻刷盘,MySQL 崩溃不会丢,OS 崩溃会丢失 1 秒内事务。
      • 0:每秒刷一次,性能最好但可能丢失 1 秒数据。
  • IO 配置:
    • innodb_read_io_threads / innodb_write_io_threads:后台 IO 线程数,根据磁盘 SSD 调整。
  • 临时表:
    • tmp_table_size、max_heap_table_size:控制内存临时表大小,超限转为磁盘临时表,影响查询速度。
  • 查询缓存(5.7 已废弃):MySQL 8.0 移除,应用层(Redis)替代。

测试价值:压测不同参数组合,观察 TPS/QPS 变化,找到适合业务的配置基线。

本文采用 CC BY-NC-SA 4.0 许可协议,转载请标明出处

评论0 条评论

还没有评论,来抢沙发。

发表评论

选填,不会公开

最多 1000 字