如果查询在from子句中包含子查询,MySQL会执行子查询,将结果放在一个临时表中,然后完成外层查询的优化,它必须在外层查询优化前处理;所有类似的子查询,explain也必须这样做,意味着如果子查询开销较大,或使用临时表,服务器开销会比较大。这时候可以使用join连接查询代替子查询。
explain对内存排序和临时文件都使用filesort,并且对于磁盘上和内存中的临时表都显示using temporary。
select_type表示简单查询,还是复杂查询,有simple(不包含子查询和union),subquery(不在from子句中),derived(from子查询中的select,将结果放在临时表中,叫派生表),union,union result(从union的匿名临时表检索结果的select语句),dependent(select依赖于外层查询中发现的数据或者相关子查询),uncacheable(select中某些特性阻止结果缓存于一个item_cache中)。table列中的derivedN表示子查询,其中N表示子查询的ID,第几个子查询。
type访问类型:依次从最差到最优all,index,range,ref(索引访问或者索引查找)。
possible_keys查询可能使用哪些索引,这个索引能高效查找数据,要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。
key列表示查询决定已经使用了哪个索引,是优化后使用的索引。
key_len列表示索引里可能使用的最大长度字节数。
ref列显示之前的表在key列记录到索引中查找值所使用的列或常量。
rows列表示为了找到所需的行而要读取的行数,所有rows行数相乘就是要读取的行数。
filtered列显示针对表里符合某个条件的记录数的百分比,也就是说把rows列和这个百分比相乘就能估算这个查询计划里前一个表关联的行数。
extra列显示了不适合在其他列显示的列,using index使用覆盖索引,using where表示服务器将在存储引擎检索后再进行过滤,using temporary对查询结果排序是使用临时表,using filesort对结果使用外部索引排序,在磁盘上或者内存上。
表锁使用lock tables创建,全局锁使用flush tables with read lock或设置read_only=1,获取全局读锁,它与任何表锁都冲突。
命名锁是表锁的一种,在服务器重命名或删除一个表时创建,字符锁使用get_lock()及相关函数锁住或释放任意一个字符串。
MySQLadmin debug可以显示哪个线程阻塞查询的表锁。
show innodb status可以显露一些锁的信息,还有information_schema数据库中显露事务和锁信息。
MySQL服务器逻辑架构:第一层连接处理,授权认证,安全等,第二层,比较核心的一层,查询解析,分析优化,缓存,内置函数,还有夸存储引擎的功能比如存储过程,触发器,视图等,第三层,包含存储引擎,负责数据的存储和提取。
事务原子性:不可分割,要么全部成功,要么。全部失败。事务一致性:状态转移,不会影响数据的变化,假如执行一半宕机,不会提交,还是原来的数据。事务隔离性:正在修改数据,其他用户不会看到。事务持久性:事务一旦提交就永久保存,即使系统崩溃也不会丢失数据。事务隔离级别:未提交读(一个事务修改数据,未提交事务,但是另一个事务已经看到之前事务修改的数据,脏读),已提交读(一个事务未提交的数据,另一个事务看不到它的数据,只有之前的事务提交了,才能看到,这样导致这个事务两次查询的数据不一致,不可重复读)。可重复读(也叫幻读,并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。或者select 某记录是否存在,存在,准备更新该记录,但执行 update时发现此记录已被删除,无法更新,此时也会产生幻读。)
innodb mvcc支持高并发,通过间隙锁next-key locking解决了这个问题,间隙锁防止幻读出现,innodb不仅仅锁住查询涉及的行,还会锁定索引中间隙,防止幻影行的出现。innodb表基于聚簇索引建立,它的二级索引必须包含主键列,如果主键列很大,其他索引也很大。
innodb的双写缓冲,它是表空间一块特殊保留区域,在一些连续的块中保留100个页,本质上是最近写回的页面的数据的拷贝。当innodb刷新缓存到磁盘,首先写到双写缓冲中,然后再写到它所属的数据区域中,保证页面数据的写入是原子性和持久化的。就是要写两遍,并且是顺序的,只调用一次fsync()刷新到磁盘,对性能没有大的影响。而且允许日志写入更加高效,因为数据安全有保障,日志不需要包含整个页,更像是页面的二进制变化量。如果不完整的页写到双写缓冲,但是原始页依然存在磁盘中,innodb恢复时,会用原始页替换双写缓冲。如果双写缓冲成功,但是写到页的真是位置失败了,innodb会用双写缓冲拷贝的数据替换掉真实位置的数据。innodb知道页面是否损坏,因为每页后面有校验值checksum。如果不需要双写缓冲,用innodb_doublewrite=0关闭。
myisam不支持事务和行级锁,支持表锁,支持全文索引,支持并发插入concurrent insert(读取查询的同时,可以插入数据)。
MySQL存储在两个文件中数据文件(以.MYD结尾)和索引文件(以MYI结尾)。