客户端先通过连接器连接到 MySQL 服务器。
连接器权限验证通过之后,先查询是否有查询缓存,如果有缓存(之前执行过此语句)则直接返回缓存数据,如果没有缓存则进入分析器。
分析器会对查询语句进行语法分析和词法分析,判断 SQL 语法是否正确,如果查询语法错误会直接返回给客户端错误信息,如果语法正确则进入优化器。
优化器是对查询语句进行优化处理,例如一个表里面有多个索引,优化器会判别哪个索引性能更好。
优化器执行完就进入执行器,执行器就开始执行语句进行查询比对了,直到查询到满足条件的所有数据,然后进行返回。
此错误是执行到分析器阶段报出的,因为 MySQL 会在分析器阶段检查 SQL 语句的正确性。
MySQL 查询缓存功能是在连接器之后发生的。 优点是效率高,如果已经有缓存则会直接返回结果。 缺点是失效太频繁导致缓存命中率比较低,任何更新表操作都会清空查询缓存,因此导致查询缓存非常容易失效。
MySQL 查询缓存默认是开启的,配置 querycachetype 参数为 DEMAND(按需使用)关闭查询缓存,MySQL 8.0 之后直接删除了查询缓存的功能。
MySQL 的常用引擎有 InnoDB、MyISAM、Memory 等,从 MySQL 5.5.5 版本开始 InnoDB 成为默认的存储引擎。
可以针对不同的表设置不同的引擎。在 create table 语句中使用 engine=引擎名(比如Memory)来设置此表的存储引擎。
create table student( id int primary key auto_increment, username varchar(120), sex tinyint(1) ) ENGINE=MemoryInnoDB 和 MyISAM 最大的区别是 InnoDB 支持事务,而 MyISAM 不支持事务,它们主要区别如下:
InnoDB 支持崩溃后安全恢复,MyISAM 不支持崩溃后安全恢复;InnoDB 支持行级锁,MyISAM 不支持行级锁,只支持到表锁;InnoDB 支持外键,MyISAM 不支持外键;MyISAM 性能比 InnoDB 高;MyISAM 支持 FULLTEXT 类型的全文索引,InnoDB 不支持 FULLTEXT 类型的全文索引,但是 InnoDB 可以使用 sphinx 插件支持全文索引,效果更好; InnoDB 主键查询性能高于 MyISAM。插入缓冲(insert buffer): 对于非聚集索引的插入和更新,不是每一次直接插入索引页中,而是首先判断插入的非聚集索引页是否在缓冲池中,如果在,则直接插入,否则,先放入一个插入缓冲区中。好似欺骗数据库这个非聚集的索引已经插入到叶子节点了,然后再以一定的频率执行插入缓冲和非聚集索引页子节点的合并操作,这时通常能将多个插入合并到一个操作中,这就大大提高了对非聚集索引执行插入和修改操作的性能。
两次写(double write): 两次写给 InnoDB 带来的是可靠性,主要用来解决部分写失败(partial page write)。doublewrite 有两部分组成,一部分是内存中的 doublewrite buffer ,大小为 2M,另外一部分就是物理磁盘上的共享表空间中连续的 128 个页,即两个区,大小同样为 2M。当缓冲池的作业刷新时,并不直接写硬盘,而是通过 memcpy 函数将脏页先拷贝到内存中的 doublewrite buffer,之后通过 doublewrite buffer 再分两次写,每次写入 1M 到共享表空间的物理磁盘上,然后马上调用 fsync 函数,同步磁盘。
自适应哈希索引(adaptive hash index): 由于 InnoDB 不支持 hash 索引,但在某些情况下 hash 索引的效率很高,于是出现了 adaptive hash index 功能, InnoDB 存储引擎会监控对表上索引的查找,如果观察到建立 hash 索引可以提高性能的时候,则自动建立 hash 索引。
脏读
修改丢失
不可重复读
幻读
脏读是一个事务在处理过程中读取了另外一个事务未提交的数据; 幻读是指同一个事务内多次查询返回的结果集不一样(比如增加了或者减少了行记录)。
因为行锁只能锁定存在的行,针对新插入的操作没有限定,所以就有可能产生幻读。 使用间隙锁的方式来避免出现幻读。
VARCHAR 和 CHAR 最大区别就是,VARCHAR 的长度是可变的,而 CHAR 是固定长度,CHAR 的取值范围为1-255,因此 VARCHAR 可能会造成存储碎片。
它们的特性决定了 CHAR 比较适合长度较短的字段和固定长度的字段,如身份证号、手机号等,反之则适合使用 VARCHAR。
MySQL 存储金额应该使用 decimal ,因为如果存储其他数据类型,比如 float 有导致小数点后数据丢失的风险。
MySQL 中支持两种模糊查询:regexp 和 like,like 是对任意多字符匹配或任意单字符进行模糊匹配,而 regexp 则支持正则表达式的匹配方式,提供比 like 更多的匹配方式。
count(字段) < count(主键 id) < count(1) ≈ count(*)
对于 count(主键 id) 来说,InnoDB 引擎会遍历整张表,把每一行的 id 值都取出来,返回给 server 层。server 层拿到 id 后,判断是不可能为空的,就按行累加。
对于 count(1) 来说,InnoDB 引擎遍历整张表,但不取值。server 层对于返回的每一行,放一个数字“1”进去,判断是不可能为空的,按行累加。
对于 count(字段) 来说,如果这个“字段”是定义为 not null 的话,一行行地从记录里面读出这个字段,判断不能为 null,按行累加;如果这个“字段”定义允许为 null,那么执行的时候,判断到有可能是 null,还要把值取出来再判断一下,不是 null 才累加。
对于 count(*) 来说,并不会把全部字段取出来,而是专门做了优化,不取值,直接按行累加。