《Mysql技术内幕》读书笔记
第一章 MySql存储引擎
1.Innodb存储引擎
支持事务,其特点是行锁设计、支持外键。
Innodb是Mysql默认的存储引擎。
2.MyISAM存储引擎
MyIsam存储引擎不支持事务和表锁设计,Myisam也不支持外键,但是支持全文索引。
第五章 索引与算法
1.常见的索引:B+树索引、全文索引、哈希索引。
2.B+树,是通过二叉查找树,再由平衡二叉树,B树演化而来。
二叉查找树
二叉查找树:左子树的值总是小于根的值,右子树的值总是大于根的值。可以通过中序遍历得到值的排序输出。
平均查找速度比顺序查找来得快。
平衡二叉树(AVL树)
平衡二叉树:首先符合二叉查找树的定义,其次必须满足任何节点的两个子树的高度的最大差为1。
B+树
B+树:是为磁盘或其他直接存取辅助设备设计的一种平衡树。
在B+树中,所有记录节点都是按键值对的大小顺序存放在同一层的叶子节点上,由各叶子节点指针进行连接。
优点:B+树的高度一般都在2--4层。也就是查找某一键值的行记录时最多只需要2--4次IO就可以了。
B+树索引
B+树索引,分为聚集索引和辅助索引。
聚集索引和辅助索引的区别:叶子节点存放的是否是一整行的信息。
聚集索引
聚集索引:就是按照每张表的主键构造一颗B+树,同时叶子节点存放的即为整张表的行记录数据,也将聚集索引的叶子节点称为数据页。
辅助索引(非聚集索引)
辅助索引:叶子节点并不包含行记录的全部数据。叶子节点除了包含键值以外,每个叶子节点中的索引行中还包含了一个书签(bookmark)。该书签用来告诉Innodb存储引擎哪里可以找到与索引相对应的行数据。辅助索引的书签就是相应行数据的聚集索引键。
Cardinality值
1.SHOW INDEX FROM 表名
:该语句可以查看表的索引信息。
2.Cardinality值非常关键,优化器会根据这个值来判断是否使用这个索引。
对于性别,地区类型的字段,可取值的范围小,称为“低选择性”,没有必要使用B+树索引。
Cardinality值,表示索引中不重复记录数量的预估值。在实际运用中,Cardinality尽可能地接近1。如果非常小,用户需要考虑是否还有必要创建这个索引。
EXPLAIN
可以查看查询类型,以及索引。
PROSSIBLE_KEY:可能的索引。
KEY:实际的索引。
联合索引
1.联合索引是指对表上的多个列进行索引。
2.联合索引也是一颗B+树,不同的是联合索引的键值的数量不是1,而是大于等于2。
联合索引的键值都是排序的。通过叶子节点可以逻辑上顺序地读出所有数据。
数据按(a,b)进行存放,排序方式类似于(1,1)、(1,2)、(2,1)、(2,4)、(3,1)、(3,2)、(4,1)。
对于单个的a列查询来说,可以使用(a,b)这个联合索引。
但对于单个的b列查询来说,则不可以使用(a,b)这个联合索引,因为叶子节点上的b值为1,2,1,4,1,2,显然不是排序的。
3.索引的第二个好处是已经对第二个键值进行了排序。
4.对于联合索引(a,b,c)来说,以下语句可以直接通过联合索引得到结果。
SELECT * FROM TABLE WHERE a=XXX ORDER BY b
SELECT * FROM TABLE WHERE a=XXX AND b=YYY ORDER BY c
SELECT * FROM TABLE WHERE a=XXX AND c=YYY
但是以下的则不行,因为最左匹配原则:
SELECT * FROM TABLE WHERE b=XXX AND c=YYY
覆盖索引
1.InnoDBd存储引擎支持覆盖索引,即从辅助索引中就可以得到查询的记录,而不需要查询聚集索引中的记录。
使用覆盖索引的一个好处是,辅助索引不包含整行记录的所有信息,故其大小要远小于聚集索引,因此可以减少大量的IO操作。
其他
1.FIC : Fast Index Creation。
2.Online DDL
哈希算法
1.哈希表也成为散列表。由直接寻址表改进而来。
哈希表,利用哈希函数h,根据关键字k计算出槽的位置。
2.哈希碰撞:两个不同的关键字,可能映射到同一槽中。成为“碰撞”。
解决碰撞的方法:链表法。把同一哈希槽中的所有元素放在一个链表中,
在槽中有一个指针j,指向链表头。
3.哈希函数,最重要是散列,减少碰撞。
4.散列算法:除法散列。
全文检索
0.全文检索:是将存储于数据库中的整本书或整篇文章的任意内容信息查找出来的技术。可以根据需要获得全文中有关章、节、段、句、词的信息。也可以进行统计和分析。
1.左模糊不走B+树索引。
2.倒排索引:在辅助表中存储了单词和单词自身在一个或多个文档中所在位置的映射。通过关联数组实现。
3.全文检索的SQL语句:
SELECT * FROM 表名 WHERE MATCH(字段名) AGAINST (‘检索的具体值‘)
锁
1.行级锁有以下两种。
共享锁:允许事务读一行数据。
排它锁:允许事务删除或更新一行数据。若有其他事务想获得排它锁,必须等原来的事务释放锁。
2.锁的相关表。information_schema架构下的表INNODB_TRX,INNODB_LOCKS,INNODB_LOCK_WAITS。
命令:SHOW ENGINE INNODB STATUS。
一致性非锁定读
1.指的是通过多行版本控制的方式读数据库。如果读取的行正在执行变更操作,这时不会等待锁释放。相反,INNODB引擎会去读取行的一个快照数据。
之所以成为非锁定读,是因为不需要等待访问的行的锁释放。
2.在READ COMMITTED事务隔离级别下,对于快照数据,非一致性读总是读取被锁定的行的最新一份快照数据。在REPEATABLE READ事务隔离级别下,对于快照数据,非一致性读总是读取事务开始时的行数据版本。
3.在事务的默认配置下,事务的隔离级别为REPEATABLE READ模式。INNODB存储引擎的SELECT操作,使用一致性非锁定读。
一致性锁定读
1.一致性锁定读,对数据库的读操作进行加锁以保证数据逻辑的一致性。
比如现在有两个线程,A线程读时另B线程改变了数据,那么在READ COMMITED隔离级别下,A线程第二次读到的是最新的数据。
2.锁定读有两种。SELECT ... FOR UPDATE和SELECT... LOCK IN SHARE MODE。
3.一致性锁定读,SELECT FOR UPDATE对读取的行记录加入一个X锁(排它锁),其他事务不能对已锁定的行加任何锁。
而对于一致性非锁定读,即使读取的行已经执行了SELECT FOR UPDATE,也是可以读取的。
4.SELECT...IN SHARE MODE对读取的行记录加上一个S锁,其他事务可以向被锁定的行加S锁,但是如果是加X锁,则会被阻塞。
锁问题
脏读
脏读:脏数据是指未提交的数据。脏读是指在不同的事务下,当前事务可以读到另外事务未提交的数据。这显然违反了数据库的隔离性。
脏读发生的事务隔离级别:READ UNCOMMITED。
不可重复读
不可重复读:在一个事务内两次读到的数据不一样。比如,A事务还没有结束,B事务对同一数据进行修改,由于B事务的修改,那么A事务两次读到的数据是不一样的。违背了数据库事务一致性的要求。
不可重复读,读到的是已经提交的数据。
不可重复读,发生的隔离级别是READ COMMITTED。
ORACLE默认的隔离级别也是READ COMMITTED。
幻读
幻读:A事务读取了B事务已经提交的新增数据。
丢失更新
丢失更新,是指一个事务的更新操作会被另一个事务的更新操作覆盖。
死锁
1.死锁是指两个或两个以上的事务,在执行过程中,因争夺资源而造成的一种互相等待的现象。
2.死锁解决方法:超时机制。
3.死锁检测:等待图。
疑惑
- 为什么Mysql索引,使用的数据结构,必须有序?
因为顺序读远远快于离散读。
为什么在B+树中新增数据,也要保证有序?
有序才能更快地找到存储的内容。
B+树还能用于磁盘。。
- 为什么要用B+树?
B+树又"矮"又"胖",能够更快地查找到内容。
- B+树为什么要把数据全放在叶子节点上面呢?
节点存储的内容是有限的,只存放指针能够使节点的高度更矮,能够更快地查找到内容。
-
为什么散列表(哈希表)数据放到一个链表中就能减少碰撞?
-
数据库锁,java的锁,和操作系统的锁,是否原理都是一样的??
-
锁是怎么处理多个事务的?
A事务开启后未提交,B事务进行其他操作,会有怎样的结果?(一致性非锁定读)
参考资料:
《Mysql技术内幕》
https://www.cnblogs.com/softidea/p/5977860.html