MySQL常见问题
# MySQL常见问题
# 1. 为什么不建议使用外键?
外键是一种约束,这种约束会保证表间数据的关系始终完整。
优点:
- 外键可以保证数据的完整性和一致性,级联操作方便
- 使用外键可以将数据完整性判断托付给数据库完成,减少程序的代码量
缺点:
- 并发问题,每次修改数据都需要去另一个表检查数据,需要获取额外的锁。若在高并发大流量事务场景,使用外键更容易造成死锁。
- 扩展性问题,比如从 MySQL 迁移到 Oracle,外键依赖于数据库本身的特性,做迁移不方便
- 不利于分库分表,在水平拆分和分库的情况下,外键是无法生效的。
# 2. 一条SQL查询语句时如何执行的?
- MySQL 客户端与服务器间建立连接,客户端发送一条查询给服务器;
- 服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果;否则进入下一阶段;
- 服务器端进行 SQL 解析、预处理,生成合法的解析树;
- 再由优化器生成对应的执行计划;
- MySQL 根据优化器生成的执行计划,调用相应的存储引擎的 API 来执行,并将执行结果返回给客户端。
# 3. MyISAM 和 InnoDB 的区别是什么?
1.是否支持行级锁
MyISAM 只有表级锁(table-level locking),而 InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。InnoDB 在并发写的时候,性能更牛皮!
2.是否支持事务
MyISAM 不提供事务支持。
InnoDB 提供事务支持,实现了 SQL 标准定义了四个隔离级别,具有提交(commit)和回滚(rollback)事务的能力。并且,InnoDB 默认使用的 REPEATABLE-READ(可重读)隔离级别是可以解决幻读问题发生的(基于 MVCC 和 Next-Key Lock)。
3.是否支持外键
MyISAM 不支持,而 InnoDB 支持。外键对于维护数据一致性非常有帮助,但是对性能有一定的损耗。因此,通常情况下,我们是不建议在实际生产项目中使用外键的,在业务代码中进行约束即可!
不过,在代码中进行约束的话,对程序员的能力要求更高,具体是否要采用外键还是要根据你的项目实际情况而定。
4.是否支持数据库异常崩溃后的安全恢复
MyISAM 不支持,而 InnoDB 支持。
使用 InnoDB 的数据库在异常崩溃后,数据库重新启动的时候会保证数据库恢复到崩溃前的状态。这个恢复的过程依赖于 redo log
。
5.是否支持 MVCC
MyISAM 不支持,而 InnoDB 支持。MVCC 可以看作是行级锁的一个升级,可以有效减少加锁操作,提高性能。
6.索引实现不一样。
虽然 MyISAM 引擎和 InnoDB 引擎都是使用 B+Tree 作为索引结构,但是两者的实现方式不太一样。
InnoDB 引擎中,其数据文件本身就是索引文件。相比 MyISAM,索引文件和数据文件是分离的,其表数据文件本身就是按 B+Tree 组织的一个索引结构,树的叶节点 data 域保存了完整的数据记录。
# 4. where 和 on 区别
on 是关联条件,where 是查询条件。
数据库在关联多张表的时候,会生成中间临时表,on 在生产临时表时使用的条件,不管 on 中的条件是否为真,都会返回主表的记录。 where 在临时表生成后,对新的临时表进行过滤。
在使用 left join 时,左表的数据在 where 中过滤,右表的过滤在 on 中进行。使用 right join 时相反,inner join 无区别。
# 为什么是varchar(255)而不是(256)
大多数的客户端在创建一个varchar类型的字段的时候,如果不指定字段的长度,默认都是使用255,为什么不是256呢? 因为varchar类型的字段长度在超过255后,比如我们使用varchar(256),varchar(256)的字段在存储到磁盘的时候,就会比varchar(255)的字段多占用1个byte的存储空间。而多出来的这一个byte的空间用来存储该字段的长度用了。
varchar(255)存储一个字符a的时候,使用1个byte表示字段的长度,1个byte用来存储字符a,此时一共使用2个bytes物理存储空间。
varchar(256)存储一个字符a的时候,使用2个bytes表示字段的长度,1个byte用来存储字符a,此时一共需要3个bytes物理存储空间。