一、MySql学习笔记

1. 数据库基础概念

  • 数据库(DB):存储数据的仓库,按一定格式组织和存储数据,便于管理和访问。

  • 数据库管理系统(DBMS):管理数据库的软件,如MySQL、Oracle、SQL Server等,提供数据定义、查询、更新、控制等功能。

  • SQL(结构化查询语言):用于与DBMS交互的标准语言,分为DQL(数据查询)、DML(数据操作)、DDL(数据定义)、DCL(数据控制)。

  • 关系型数据库(RDBMS):基于关系模型(二维表结构)的数据库,数据之间存在关联关系,支持ACID特性,MySQL是典型的RDBMS。

2. MySQL核心特性

  • ACID特性:事务的四大特性,保证数据的安全性和一致性。
    原子性(Atomicity):事务是不可分割的最小单位,要么全部执行,要么全部不执行。

  • 一致性(Consistency):事务执行前后,数据库的完整性约束不被破坏(如主键唯一、外键关联正常)。

  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不会被其他事务干扰。

  • 持久性(Durability):事务一旦提交,其对数据库的修改会永久保存,即使数据库崩溃也不会丢失。

存储引擎:MySQL的核心组件,负责数据的存储和读取,不同引擎有不同特性,常用的有InnoDB、MyISAM。
InnoDB:默认存储引擎,支持事务、行级锁、外键,适合高并发、数据一致性要求高的场景(如电商订单、金融数据)。

MyISAM:不支持事务和行级锁,支持表级锁,查询速度快,适合读多写少的场景(如博客文章、静态数据)。

索引:帮助MySQL高效查询数据的数据结构(如B+树、哈希表),相当于书的目录,能大幅提升查询效率,但会降低插入、更新、删除的效率(需维护索引)。

锁机制:用于解决并发访问时的数据竞争问题,分为表级锁(锁定整个表,开销小、并发低)和行级锁(锁定单行数据,开销大、并发高)。

3. 索引相关知识点

  • 索引类型
    主键索引(PRIMARY KEY):唯一标识一条记录,主键字段非空且唯一,一张表只能有一个主键索引。

  • 唯一索引(UNIQUE):索引字段的值唯一,但允许为空,一张表可以有多个唯一索引。

  • 普通索引(INDEX):最基础的索引,无任何约束,仅用于提升查询效率。

  • 联合索引(复合索引):由多个字段组合而成的索引,遵循“最左匹配原则”(查询时需从索引的第一个字段开始匹配,否则索引失效)。

  • 全文索引(FULLTEXT):用于全文检索,适用于CHAR、VARCHAR、TEXT类型的字段,MyISAM和InnoDB(5.6+)均支持。

索引底层数据结构
B+树:MySQL默认索引结构,非叶子节点存储索引值,叶子节点存储数据地址(InnoDB)或数据(MyISAM),叶子节点之间通过链表连接,便于范围查询。

哈希表:适用于等值查询(如memcached),但不支持范围查询和排序,MySQL中仅Memory引擎支持哈希索引。

索引失效场景
使用SELECT * 查询(无法使用覆盖索引)。

索引字段使用函数(如SUBSTR(name,1,3))、运算(如id+1=10)。

索引字段使用模糊查询(如name LIKE ‘%张三’,%开头会导致索引失效;LIKE ‘张三%’ 则索引有效)。

联合索引未遵循最左匹配原则(如联合索引(a,b,c),查询条件为b=2、c=3时索引失效)。

使用OR连接条件,其中一侧字段无索引(如id=1 OR name=’张三’,若name无索引则整个查询不使用索引)。

4. 事务隔离级别

MySQL默认隔离级别为RR(可重复读),不同隔离级别对应不同的并发问题,隔离级别从低到高如下:

  • 读未提交(Read Uncommitted):最低隔离级别,允许读取未提交的事务数据,会导致“脏读”(读取到其他事务未提交的修改)。

  • 读已提交(Read Committed,RC):只能读取已提交的事务数据,解决脏读问题,但会导致“不可重复读”(同一事务内多次查询同一数据,结果不一致,因为其他事务修改并提交了该数据)。

  • 可重复读(Repeatable Read,RR):同一事务内多次查询同一数据,结果一致,解决不可重复读问题,但会导致“幻读”(同一事务内多次执行同一范围查询,结果集行数不一致,因为其他事务插入了符合条件的数据)。InnoDB通过MVCC(多版本并发控制)解决了幻读问题。

  • 串行化(Serializable):最高隔离级别,事务串行执行,完全避免脏读、不可重复读、幻读,但并发效率极低,适合数据一致性要求极高的场景(如金融交易)。

查看隔离级别命令:SELECT @@transaction_isolation;

设置隔离级别命令:SET SESSION TRANSACTION ISOLATION LEVEL 隔离级别;(如SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;)

5. MVCC(多版本并发控制)

InnoDB实现隔离级别的核心技术,通过保存数据的多个版本,允许不同事务在并发访问时读取不同版本的数据,避免加锁(读不加锁,写加锁),提升并发效率。核心原理:

  • 每行数据包含隐藏列:DB_TRX_ID(事务ID,记录修改该数据的事务)、DB_ROLL_PTR(回滚指针,指向该数据的上一个版本)。

  • undo log(回滚日志):保存数据的历史版本,通过回滚指针串联,事务读取数据时,根据事务ID和隔离级别选择合适的版本(快照读)。

  • 快照读:普通SELECT查询(非锁定读),读取undo log中的历史版本,不加锁;当前读:SELECT … FOR UPDATE、SELECT … LOCK IN SHARE MODE、INSERT、UPDATE、DELETE,读取当前最新版本,加锁。

二、常用命令汇总

1. 数据库操作(DDL)

  • 查看所有数据库:SHOW DATABASES;

  • 创建数据库:CREATE DATABASE 数据库名 [CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci];(utf8mb4支持emoji,推荐使用)

  • 使用数据库:USE 数据库名;

  • 删除数据库:DROP DATABASE 数据库名;(谨慎使用,数据不可恢复)

  • 查看当前使用的数据库:SELECT DATABASE();

2. 表操作(DDL)

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

  • 创建表:
    CREATE TABLE 表名 ( 字段名1 数据类型 [约束条件], 字段名2 数据类型 [约束条件], ... [PRIMARY KEY (字段名)], [FOREIGN KEY (字段名) REFERENCES 关联表名(关联字段名)] ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    示例:
    CREATE TABLE user ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID', username VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名', password VARCHAR(100) NOT NULL COMMENT '密码', age INT DEFAULT 0 COMMENT '年龄', create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

  • 查看表结构:DESC 表名;SHOW COLUMNS FROM 表名;

  • 修改表名:ALTER TABLE 旧表名 RENAME TO 新表名;

  • 添加字段:ALTER TABLE 表名 ADD 字段名 数据类型 [约束条件] [AFTER 已有字段名];(AFTER指定字段位置,默认在最后)

  • 修改字段:ALTER TABLE 表名 MODIFY 字段名 新数据类型 [新约束条件];(修改数据类型或约束)或 ALTER TABLE 表名 CHANGE 旧字段名 新字段名 新数据类型 [新约束条件];(修改字段名)

  • 删除字段:ALTER TABLE 表名 DROP 字段名;

  • 删除表:DROP TABLE 表名;(谨慎使用)

3. 数据操作(DML)

  • 插入数据:
    -- 插入单条数据 INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...); -- 插入多条数据 INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...), (值1, 值2, ...), ...;
    示例:INSERT INTO user (username, password, age) VALUES ('zhangsan', '123456', 20), ('lisi', '654321', 22);

  • 更新数据:UPDATE 表名 SET 字段名1=值1, 字段名2=值2, ... WHERE 条件;(WHERE条件必加,否则更新全表数据)

  • 删除数据:
    -- 删除符合条件的数据(可恢复,因为会记录undo log) DELETE FROM 表名 WHERE 条件; -- 清空表数据(不可恢复,速度快,不记录日志) TRUNCATE TABLE 表名;

4. 数据查询(DQL)

  • 基础查询:
    -- 查询指定字段 SELECT 字段名1, 字段名2, ... FROM 表名; -- 查询所有字段(不推荐,效率低) SELECT * FROM 表名; -- 去重查询 SELECT DISTINCT 字段名 FROM 表名; -- 别名查询 SELECT 字段名 AS 别名 FROM 表名;

  • 条件查询(WHERE):
    SELECT 字段名 FROM 表名 WHERE 条件; -- 常用条件运算符:=、!=、<、>、<=、>=、BETWEEN...AND...、IN、NOT IN、LIKE、IS NULL、IS NOT NULL 示例: SELECT * FROM user WHERE age BETWEEN 18 AND 30; -- 年龄在18-30之间 SELECT * FROM user WHERE username LIKE '张%'; -- 用户名以“张”开头 SELECT * FROM user WHERE age IS NOT NULL; -- 年龄不为空

  • 排序查询(ORDER BY):
    SELECT 字段名 FROM 表名 ORDER BY 字段名1 [ASC|DESC], 字段名2 [ASC|DESC]; -- ASC:升序(默认),DESC:降序 示例:SELECT * FROM user ORDER BY age DESC, create_time ASC;

  • 分页查询(LIMIT):
    -- 语法:LIMIT 偏移量, 每页条数(偏移量=(页码-1)*每页条数) SELECT 字段名 FROM 表名 LIMIT 0, 10; -- 第1页,10条数据 SELECT 字段名 FROM 表名 LIMIT 10, 10; -- 第2页,10条数据

  • 聚合查询(GROUP BY + 聚合函数):
    -- 聚合函数:COUNT(统计数量)、SUM(求和)、AVG(求平均)、MAX(最大值)、MIN(最小值) SELECT 聚合函数(字段名) FROM 表名 GROUP BY 分组字段 HAVING 分组条件; -- WHERE vs HAVING:WHERE过滤行数据(分组前),HAVING过滤分组数据(分组后) 示例: SELECT age, COUNT(*) AS user_count FROM user GROUP BY age HAVING COUNT(*) > 1;

  • 多表连接查询:
    -- 内连接(只查询匹配的数据) SELECT a.字段名, b.字段名 FROM 表a a INNER JOIN 表b b ON a.关联字段 = b.关联字段; -- 左连接(查询表a所有数据,表b匹配的数据,不匹配则为NULL) SELECT a.字段名, b.字段名 FROM 表a a LEFT JOIN 表b b ON a.关联字段 = b.关联字段; -- 右连接(查询表b所有数据,表a匹配的数据,不匹配则为NULL) SELECT a.字段名, b.字段名 FROM 表a a RIGHT JOIN 表b b ON a.关联字段 = b.关联字段;

5. 索引操作(DDL)

  • 创建索引:
    -- 普通索引 CREATE INDEX 索引名 ON 表名(字段名); -- 唯一索引 CREATE UNIQUE INDEX 索引名 ON 表名(字段名); -- 联合索引 CREATE INDEX 索引名 ON 表名(字段名1, 字段名2, ...); -- 全文索引 CREATE FULLTEXT INDEX 索引名 ON 表名(字段名);

  • 查看索引:SHOW INDEX FROM 表名;

  • 删除索引:DROP INDEX 索引名 ON 表名;

6. 事务操作(DML)

  • 开启事务:START TRANSACTION;BEGIN;

  • 提交事务:COMMIT;(事务执行成功,持久化数据)

  • 回滚事务:ROLLBACK;(事务执行失败,撤销所有修改)

  • 保存点:
    START TRANSACTION; UPDATE user SET age=21 WHERE id=1; SAVEPOINT sp1; -- 设置保存点 UPDATE user SET age=22 WHERE id=2; ROLLBACK TO sp1; -- 回滚到保存点(仅撤销id=2的修改,id=1的修改保留) COMMIT;

7. 权限管理(DCL)

  • 创建用户:CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';(主机名用%表示所有主机可访问)

  • 授权用户:GRANT 权限1, 权限2, ... ON 数据库名.表名 TO '用户名'@'主机名';(权限如SELECT、INSERT、UPDATE、DELETE、ALL PRIVILEGES(所有权限))

  • 查看权限:SHOW GRANTS FOR '用户名'@'主机名';

  • 撤销权限:REVOKE 权限1, 权限2, ... ON 数据库名.表名 FROM '用户名'@'主机名';

  • 删除用户:DROP USER '用户名'@'主机名';

三、高频面试题及答案

1. 基础概念类

Q1:MySQL中InnoDB和MyISAM的区别?

A:核心区别如下:

  • 事务支持:InnoDB支持事务,MyISAM不支持。

  • 锁机制:InnoDB支持行级锁和表级锁,MyISAM仅支持表级锁。

  • 外键支持:InnoDB支持外键,MyISAM不支持。

  • 存储结构:InnoDB将数据和索引存储在一个文件(.ibd),MyISAM分为数据文件(.MYD)和索引文件(.MYI)。

  • 查询效率:MyISAM查询速度快(适合读多写少),InnoDB写入、更新效率高(适合高并发、写多读少)。

  • 崩溃恢复:InnoDB支持崩溃恢复(通过redo log),MyISAM不支持,崩溃后可能丢失数据。

Q2:什么是事务?事务的ACID特性是什么?

A:事务是数据库中一组不可分割的操作单元,要么全部执行,要么全部不执行。ACID特性如下:

  • 原子性(Atomicity):事务是最小执行单位,不可拆分,要么全成功,要么全失败。

  • 一致性(Consistency):事务执行前后,数据库的完整性约束(如主键唯一、外键关联)不被破坏。

  • 隔离性(Isolation):多个事务并发执行时,一个事务的操作不会被其他事务干扰。

  • 持久性(Durability):事务提交后,对数据库的修改永久保存,即使数据库崩溃也不会丢失。

Q3:MySQL的事务隔离级别有哪些?默认是哪个?各隔离级别会出现什么并发问题?

A:隔离级别从低到高为:读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)、串行化(Serializable)。MySQL默认隔离级别是可重复读(RR)。

各隔离级别对应的并发问题:

  • 读未提交:存在脏读、不可重复读、幻读。

  • 读已提交:解决脏读,存在不可重复读、幻读。

  • 可重复读:解决脏读、不可重复读,InnoDB通过MVCC解决了幻读,理论上存在幻读。

  • 串行化:解决所有并发问题,事务串行执行,并发效率极低。

2. 索引类

Q1:什么是索引?索引的作用是什么?优缺点是什么?

A:索引是帮助MySQL高效查询数据的数据结构,相当于书的目录。

作用:提升查询效率,减少数据库扫描的数据量。

优点:1. 大幅提升查询速度;2. 减少排序和分组操作的时间(索引本身有序)。

缺点:1. 增加存储开销(索引需要占用磁盘空间);2. 降低写入效率(插入、更新、删除时需维护索引);3. 索引过多会增加优化器的选择成本。

Q2:MySQL索引的底层数据结构是什么?为什么用B+树而不用B树或哈希表?

A:MySQL默认索引结构是B+树(InnoDB和MyISAM均使用)。

选择B+树的原因:

  • 对比B树:B+树非叶子节点仅存储索引值,不存储数据,因此非叶子节点占用空间更小,可在内存中缓存更多索引,减少磁盘I/O(磁盘I/O是数据库性能瓶颈);B+树叶子节点通过链表连接,便于范围查询(B树需遍历整棵树)。

  • 对比哈希表:哈希表仅支持等值查询(查询速度快),不支持范围查询、排序、模糊查询;哈希表存在哈希冲突问题,MySQL中仅Memory引擎支持哈希索引,适用场景有限。

Q3:什么是联合索引?联合索引的最左匹配原则是什么?

A:联合索引是由多个字段组合而成的索引(如INDEX idx_a_b_c(a,b,c))。

最左匹配原则:查询时需从联合索引的第一个字段开始匹配,否则索引失效。例如:

  • 查询条件a=1 → 匹配索引,有效。

  • 查询条件a=1 AND b=2 → 匹配索引,有效。

  • 查询条件a=1 AND b=2 AND c=3 → 匹配索引,有效。

  • 查询条件b=2 → 不匹配第一个字段,索引失效。

  • 查询条件b=2 AND c=3 → 不匹配第一个字段,索引失效。

  • 查询条件a=1 AND c=3 → 仅匹配a字段,b字段缺失,索引仅a字段生效,c字段不生效。

Q4:哪些场景下索引会失效?

A:常见索引失效场景:

  • 使用SELECT * 查询(无法使用覆盖索引,可能导致全表扫描)。

  • 索引字段使用函数(如SUBSTR(name,1,3)、DATE(create_time))或运算(如id+1=10、age*2=40)。

  • 索引字段使用模糊查询且%开头(如name LIKE ‘%张三’,%开头会导致索引失效;LIKE ‘张三%’ 则索引有效)。

  • 联合索引未遵循最左匹配原则。

  • 使用OR连接条件,其中一侧字段无索引(如id=1 OR name=’张三’,若name无索引则整个查询不使用索引)。

  • 索引字段的值为NULL(IS NULL可能失效,取决于MySQL版本和数据分布,建议字段设置默认值)。

  • 数据量过小(MySQL优化器认为全表扫描比走索引更快)。

3. 事务与并发类

Q1:什么是脏读、不可重复读、幻读?如何解决?

A:

  • 脏读:一个事务读取到另一个事务未提交的修改数据。例如:事务A更新了数据但未提交,事务B读取了该数据,随后事务A回滚,事务B读取的数据是“脏数据”。解决:提升隔离级别到读已提交(RC)及以上。

  • 不可重复读:同一事务内多次查询同一数据,结果不一致(因为其他事务修改并提交了该数据)。例如:事务A两次查询id=1的用户年龄,第一次查询为20,期间事务B将年龄改为22并提交,事务A第二次查询为22。解决:提升隔离级别到可重复读(RR)及以上。

  • 幻读:同一事务内多次执行同一范围查询,结果集行数不一致(因为其他事务插入了符合条件的数据)。例如:事务A查询年龄>18的用户有10条,期间事务B插入了1条年龄20的用户并提交,事务A再次查询为11条。解决:InnoDB通过MVCC解决幻读;或提升隔离级别到串行化。

Q2:InnoDB的MVCC原理是什么?

A:MVCC(多版本并发控制)是InnoDB实现隔离级别的核心技术,通过保存数据的多个版本,允许不同事务并发访问时读取不同版本的数据,实现“读不加锁,写加锁”,提升并发效率。核心原理:

  • 每行数据包含隐藏列:DB_TRX_ID(事务ID,记录修改该数据的事务)、DB_ROLL_PTR(回滚指针,指向该数据的上一个版本)。

  • undo log(回滚日志):保存数据的历史版本,通过回滚指针串联成版本链。当事务修改数据时,InnoDB会先将数据的旧版本写入undo log,再修改当前数据。

  • Read View(读视图):事务开启时生成的一个“快照”,包含当前活跃事务的ID列表。事务读取数据时,通过Read View判断数据版本是否可见:
    若数据的DB_TRX_ID小于Read View中的最小活跃事务ID → 数据可见(该事务已提交)。

  • 若数据的DB_TRX_ID大于Read View中的最大活跃事务ID → 数据不可见(该事务在当前事务开启后才启动)。

  • 若数据的DB_TRX_ID在活跃事务ID列表中 → 数据不可见(该事务未提交);否则可见。

快照读与当前读:普通SELECT查询是快照读(读取undo log中的历史版本,不加锁);SELECT … FOR UPDATE、INSERT、UPDATE、DELETE是当前读(读取最新版本,加锁)。

Q3:InnoDB的锁机制有哪些?行级锁的实现原理是什么?

A:InnoDB支持表级锁和行级锁,行级锁是InnoDB的核心锁机制。

  • 表级锁:锁定整个表,开销小、加锁快,并发度低,适用于全表操作(如ALTER TABLE)。分为表共享锁(S锁,允许其他事务读,禁止写)和表排他锁(X锁,禁止其他事务读和写)。

  • 行级锁:锁定单行数据,开销大、加锁慢,并发度高,适用于高并发场景。分为行共享锁(S锁,允许其他事务读该行,禁止写)和行排他锁(X锁,禁止其他事务读和写该行)。

  • 意向锁:表级锁,用于标识表中是否有行级锁,避免表级锁和行级锁的冲突。分为意向共享锁(IS锁,事务准备给表中某些行加S锁)和意向排他锁(IX锁,事务准备给表中某些行加X锁)。

行级锁的实现原理:InnoDB的行级锁是基于索引实现的,若查询语句未使用索引(全表扫描),则会升级为表级锁。例如:UPDATE user SET age=21 WHERE id=1(id是主键索引) → 加行级锁;UPDATE user SET age=21 WHERE username=’zhangsan’(username无索引) → 加表级锁。

4. 性能优化类

Q1:MySQL查询优化的常用方法有哪些?

A:常用查询优化方法:

  • 合理创建索引:针对查询频繁的字段创建索引,避免索引过多;使用联合索引时遵循最左匹配原则;避免索引失效场景。

  • 优化SQL语句:
    避免SELECT *,只查询需要的字段(使用覆盖索引)。

  • 避免使用子查询,改用JOIN(子查询可能导致全表扫描,JOIN效率更高)。

  • 避免使用OR,改用IN(OR可能导致索引失效,IN在数据量小时效率高)。

  • 使用LIMIT分页,避免一次性查询大量数据。

  • 避免在WHERE条件中使用函数或运算。

优化表结构:
选择合适的数据类型(如用INT代替VARCHAR存储数字,用VARCHAR代替TEXT存储短文本)。

字段设置为NOT NULL(避免NULL值导致索引失效,减少存储开销)。

使用自增主键(InnoDB主键索引是聚簇索引,自增主键可避免索引碎片)。

分库分表:当数据量过大(如千万级、亿级)时,单库单表性能瓶颈明显,可通过分库(按业务拆分数据库)、分表(水平分表:按数据范围或哈希拆分;垂直分表:按字段拆分)提升性能。

开启查询缓存(MySQL 8.0已移除):对于查询频繁且数据不常变化的场景,开启查询缓存可提升效率。

使用慢查询日志定位问题:开启慢查询日志(long_query_time设置阈值,如2秒),记录执行时间过长的SQL,针对性优化。

Q2:什么是分库分表?分库分表的方案有哪些?

A:分库分表是解决海量数据存储和高并发访问的核心方案,当单库数据量过大(如超过1000万)或单表数据量过大(如超过500万)时,会导致查询、写入效率下降,此时需要将数据库或表拆分。

分库分表方案:

  • 分库:
    垂直分库:按业务模块拆分(如电商系统拆分为用户库、订单库、商品库),降低单库压力,便于维护。

  • 水平分库:按数据范围或哈希拆分(如按用户ID哈希拆分到多个用户库),分担单库的并发压力。

分表:
垂直分表:按字段拆分(将大字段如TEXT拆分到单独的表,主表存储常用小字段),减少主表数据量,提升查询效率。

水平分表:按数据范围(如按时间拆分订单表:order_202401、order_202402)或哈希(如按用户ID哈希拆分用户表:user_00、user_01)拆分,减少单表数据量。

分库分表工具:Sharding-JDBC、MyCat等。

Q3:什么是慢查询日志?如何开启和使用?

A:慢查询日志是MySQL记录执行时间超过阈值(long_query_time)的SQL语句的日志,用于定位性能低下的SQL,是查询优化的重要工具。

开启和使用步骤:

  • 查看慢查询日志状态:SHOW VARIABLES LIKE 'slow_query_log';(ON为开启,OFF为关闭)。

  • 开启慢查询日志:SET GLOBAL slow_query_log = ON;(临时开启,重启MySQL失效);永久开启需修改my.cnf配置文件:
    [mysqld] slow_query_log = 1 slow_query_log_file = /var/lib/mysql/mysql-slow.log(日志存储路径) long_query_time = 2(阈值,单位秒,默认10秒) log_queries_not_using_indexes = 1(记录未使用索引的SQL)

  • 查看慢查询日志:直接查看日志文件(如cat /var/lib/mysql/mysql-slow.log),或使用mysqldumpslow工具分析(如mysqldumpslow -s t -t 10 /var/lib/mysql/mysql-slow.log:按执行时间排序,显示前10条慢查询)。

5. 其他常见问题

Q1:MySQL中的主键和唯一索引的区别?

A:核心区别:

  • 非空约束:主键字段必须非空(NOT NULL),唯一索引字段可以为空(NULL)。

  • 数量限制:一张表只能有一个主键,可多个唯一索引。

  • 索引类型:InnoDB中主键索引是聚簇索引(数据和索引存储在一起),唯一索引是非聚簇索引(索引存储数据地址)。

  • 用途:主键用于唯一标识一条记录,唯一索引仅用于保证字段值唯一。

Q2:什么是聚簇索引和非聚簇索引?区别是什么?

A:聚簇索引和非聚簇索引是InnoDB中的两种索引类型:

  • 聚簇索引(Clustered Index):
    索引和数据存储在一起,索引的叶子节点直接存储数据。

  • InnoDB中默认主键索引是聚簇索引,若表无主键,则选择唯一索引作为聚簇索引;若也无唯一索引,则InnoDB自动生成一个隐藏的聚簇索引。

  • 查询效率高,因为找到索引就找到了数据。

非聚簇索引(Non-Clustered Index):
索引和数据分开存储,索引的叶子节点存储数据的地址(聚簇索引的索引值)。

普通索引、唯一索引(非主键)均为非聚簇索引。

查询时需要先通过非聚簇索引找到聚簇索引的索引值,再通过聚簇索引找到数据,称为“回表查询”,效率比聚簇索引低。

区别:聚簇索引索引和数据一体,查询效率高,一张表仅一个;非聚簇索引索引和数据分离,需回表查询,效率较低,一张表可多个。

Q3:MySQL如何实现主从复制?主从复制的作用是什么?

A:主从复制是MySQL实现高可用、读写分离的基础,通过将主库(Master)的binlog日志同步到从库(Slave),并在从库重放日志,实现主从数据一致。

主从复制原理(三步曲):

  • 主库将数据修改记录写入binlog日志(二进制日志)。

  • 从库的IO线程连接主库,读取主库的binlog日志,写入从库的relay log(中继日志)。

  • 从库的SQL线程读取relay log,重放日志中的SQL语句,同步主库数据。

主从复制的作用:

  • 读写分离:主库负责写入(INSERT、UPDATE、DELETE),从库负责读取(SELECT),提升并发访问能力。

  • 数据备份:从库作为主库的备份,避免主库数据丢失。

  • 高可用:主库故障时,可将从库切换为主库,保证服务连续性。