作为后端猿的我们,不出意外每天都会和mysql打交道。除了每天写不腻的CURD语句,关于mysql我们应该要了解它的那些基础知识呢?
在进入文章之前,小编想给你们一个小小的福利,关于MySQL的学习结构指南,让你学习事半功倍
因为内容太多所以只放这两张图,更多资料转发+关注私信小编即可获取哦
隔离级别 脏读 不可重复读 幻读 Read Uncommitted √ √ √ Read Committed × √ √ Repeatable Read × × √ Serializable × × ×
MVCC:Multi Version Concurrency Control, 多版本并发控制,mysql防止幻读的一种技术手段。每行数据存在间隙行,间隙行存放该行数据的创建时间,删除时间,这里的时间实际是事务的版本号。当,
select数据时:只查询创建时间小于等于当前事务版本号 -> 当前事务或当前事务之前插入的行,删除时间大于当前版本号的行 -> 当前事务版本前未被删除的行。update数据时:在原有行a的基础上复制行a',行a的删除时间设置为当前的事务版本号,行a'的创建时间设置为当前的事务版本号。insert数据时:记录创建时间为当前事务版本号。delete数据时:记录删除时间为当前事务版本号。死锁产生的原因是两个事务互相等待对方释放,产生了循环依赖,mysql采用了死锁检测(检测到循环依赖返回错误)和死锁超时(超时回滚持有行锁最少的事务)的方式尽可能去避免死锁。例如:
行锁: UPDATE `table_demo` SET `a` = 'test' WHERE `b` = 'lalala'; UPDATE `table_demo` SET `b` = 'test' WHERE `a` = 'lalala'; UPDATE `table_demo` SET `b` = 'test' WHERE `a` = 'lalala'; UPDATE `table_demo` SET `a` = 'test' WHERE `b` = 'lalala'; 复制代码覆盖索引:要查询的行被索引覆盖,从索引中可以直接读取,不需要回表查询。例如:
CREATE TABLE `demo_table`( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID', `username` char(32) NOT NULL DEFAULT '' COMMENT '用户名', `password` char(32) NOT NULL DEFAULT '' COMMENT '密码', PRIMARY KEY (`id`), KEY `idx_username` (`username`) )ENGINE=InnoDB DEFAULT CHARSET=UTF8; 复制代码 explain select `username` from `demo_table` where `username` = 'demo'; +----+-------------+------------+------+---------------+--------------+---------+-------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+------+---------------+--------------+---------+-------+------+--------------------------+ | 1 | SIMPLE | demo_table | ref | idx_username | idx_username | 96 | const | 1 | Using where; Using index | +----+-------------+------------+------+---------------+--------------+---------+-------+------+--------------------------+ 复制代码Extra里的Using index就是使用了覆盖索引的意思。
个人目前理解:例如使用联合索引,从左向右依次匹配,未匹配到索引字段或第一个范围查找(between、like、大于、小于)为止,及该部分索引有效。
红黑树本质是二叉树,每个节点最多拥有两个子节点,所以红黑树的深度较深。
B树每个节点最多可以有n个子节点,根节点常驻内存且每个节点刚好申请1个页的大小,假如每个节点拥有100个子节点,那百万级的数据我们基本上只需要深度是3就可以存下 => 100^3,这样就减少的io次数(一个节点的大小通常为磁盘一个页的大小)。
又有“局部性原理”(一旦一个数据被查询,那么它附近的数据可能也会需要被查询),其次B+树的叶子节点构成一个链表,这样我们就可以很容易的查询出一段范围的数据,其次B+树的根节点和内部节点只存放该索引下一个子节点的位置的指针,数据只存放在叶子节点里,这样非叶子节点就可以有更多的空间存放索引的位置,索引的范围就可以尽可能的大,从而树的深度就可能的小。