Mysql面试笔记
2025-10-20 12:37:19 0 举报AI智能生成
Mysql面试笔记
数据库
mysql
java
开发
面试
模版推荐
作者其他创作
大纲/内容
<b>时间复杂度<br></b>查询复杂度通常指的是执行数据库查询所需的计算资源量,这通常与时间复杂度和空间复杂度有关。时间复杂度是指完成查询所需要的时间,而空间复杂度是指执行查询所需要的存储空间。这些复杂度通常用大O表示法来描述。<br><ul><li><span style="font-size:inherit;">常数时间(O(1)):不管数据集的大小如何,操作都能在恒定的时间内完成。例如,通过哈希表进行键值对查询通常是常数时间复杂度。</span></li><li>对数时间(O(log n)):随着数据集大小的增加,所需的额外时间以对数方式增加。二分查找和在平衡二叉搜索树(如AVL树)或B+树中进行查找通常是对数时间复杂度。</li><li>线性时间(O(n)):所需的时间与数据集的大小成正比。例如,如果没有索引,数据库可能需要遍历每一行来查找特定的数据。</li><li>线性对数时间(O(n log n)):这个复杂度介于线性时间和对数时间之间。一些排序算法(如快速排序和归并排序)通常具有这种复杂度。</li><li>二次时间(O(n^2)):时间复杂度与数据集大小的平方成正比。某些简单的排序算法(如冒泡排序)和具有双重嵌套循环的算法通常具有这种复杂度。</li><li>指数时间(O(2^n)):这是一种非常高的复杂度,其中所需的时间随着数据集大小的增加而呈指数增长。某些递归算法在处理大数据集时可能会遇到这种复杂度。</li><li>阶乘时间(O(n!)):这是最不可取的复杂度之一,因为时间随数据集大小的增加而呈阶乘增长。一个典型的例子是解决旅行商问题的暴力算法。</li></ul>
索引
<b>索引原理<br></b><ul><li><span style="color:rgb(231, 79, 76); font-size:inherit;">索引就是排好序的数据结构。</span></li><li><span style="font-size:inherit;">数据以页为最小单位,一页大小16kb(默认)。</span></li><li><span style="font-size:inherit;">一张表最多创建16个索引。</span></li><li><span style="font-size:inherit;">在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这就是索引。</span></li></ul><b><br>索引类型</b><br><ul><li>主键索引<br>建立在<font color="#e74f4c">主键上的索引</font>,一张表只能有一个主键索引,不可重复,不可为NULL。</li><li>唯一索引<br>建立在<font color="#e74f4c">UNIQUE字段上的索引</font>,数据列不允许重复,可以为(一个)NULL,一张表中允许创建多个唯一索引。</li><li><span style="font-size:inherit;">普通索引<br></span>建立在<font color="#e74f4c">普通字段上的基本索引</font>类型,没有唯一约束,允许为NULL。</li></ul><ul><li><span style="font-size:inherit;">复合索引(Composite Index):<br></span>也称为<font color="#e74f4c">多列索引</font>,它是在表的多个列上创建的索引。复合索引可以极大地提高查询性能,尤其是当查询条件涉及到索引中的列时。</li><li><span style="font-size:inherit;">前缀索引<br></span>指对字符类型字段的前几个字符建立的索引(减少空间占用,提升索引效率,不支持order by、group by)。</li></ul><br><b><span style="font-size:inherit;">索引设计原则</span><br></b><ul><li><span style="font-size:inherit;">最左匹配原则,尽量使用组合索引。</span></li><li><span style="font-size:inherit;">短索引,如果字符串列创建索引,应该指定前缀长度,节省空间。</span></li><li><span style="font-size:inherit;">更新频繁的列不适合创建索引。</span></li><li><span style="font-size:inherit;">避免过度索引,维护索引会消耗性能,占用更多磁盘空间,不是越多越好。</span></li></ul><br><b><span style="font-size:inherit;">索引失效原因</span><br></b><ul><li><span style="font-size:inherit;">以'%'开头的like查询</span></li><li><span style="font-size:inherit;">组合索引中没有使用第一个索引(不符合最左匹配原则)</span></li><li><span style="font-size:inherit;">使用 is null、is not null</span></li><li><span style="font-size:inherit;">使用 not、<>、!=</span></li><li><span style="font-size:inherit;">or语句前后没有同时使用索引</span></li><li><span style="font-size:inherit;">索引字段是字符类型,但是条件查询时未使用引号引用起来</span></li><li><span style="font-size:inherit;">索引字段使用运算或函数</span></li><li><span style="font-size:inherit;">(数据很少时)Mysql估计使用全表扫描要比使用索引快,则不使用索引</span></li><li><span style="font-size:inherit;">左连接查询或者右连接查询查询关联的字段编码格式不一样</span></li></ul><br><b><span style="font-size:inherit;">索引优缺点</span><br></b><ul><li><span style="font-size:inherit;">优点:提高查询效率,减少磁盘I/O次数</span></li><li><span style="font-size:inherit;">缺点:创建索引需要消耗磁盘空间,修改数据需要维护索引,产生性能消耗</span></li></ul>
数据结构(演变)
<b>Hash</b><br><ul><li>规则:根据hash值单个查询时间复杂度O(1)。</li><li>问题:范围查找、排序查找时会退化成O(N)。</li></ul>
<b>二叉树</b><br><ul><li>规则:一个节点最<font color="#e74f4c">多只能有两个子节点,左子节点比父节点小,右子节点比父节点大</font>,查询效率O(log n)。</li><li>问题:可能出现<font color="#e74f4c">左倾或右倾</font>的情况,这时退化成链表,查询复杂度退化为O(N)。</li></ul>
<b>平衡二叉树(AVL)</b><br><ul><li>规则:与二叉树类似,但是会自动调整节点,达到平衡的效果,避免退化成链表。</li><li>问题:如果数据量很大,那树高会很高,从而导致磁盘I/O过多,效率下降。</li></ul>
<b>红黑树</b><br><ul><li><font color="#e74f4c">自平衡二叉查找树</font>,是平衡二叉树的一种,在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。<br>1、查询性能要好于平衡二叉树。<br>2、红黑树是二叉查找树和平衡二叉树两者优缺点的一种折中。<br>3、可以防止出现二叉查找树左倾右倾的情况,可以减少插入时平衡的次数。<br><br></li><li>特征<br>1、根节点是黑色。<br>2、节点颜色或红或黑。<br>3、每个红色节点的两个子节点都是黑色(从每个叶子到根的所有路径上不能有两个连续的红色节点)。<br>4、所有叶子都是黑色(叶子是NIL节点)。<br>5、从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点(这里指到叶子节点的路径)。<br><br></li><li>旋转变色规则<br>1、变色情况:当前节点的<font color="#e74f4c">父节、叔父节点都是红色。<br></font>(1)父节点设为黑色<br>(2)叔父节点设为黑色<br>(3)祖父节点设为红色<br>(4)将指针定位到祖父节点,设置为要操作的节点<br>2、左旋:当前父节点是红色,叔父节点是黑色,且当前节点是<font color="#e74f4c">右子树</font><span style="font-size:inherit;">,基于父节点左旋。<br></span>3、右旋:当前父节点是红色,叔父节点是黑色,且当前节点是<font color="#e74f4c">左子树。<br></font>(1)父节点设为黑色<br>(2)祖父节点设为红色<br>(3)基于祖父节点右旋</li></ul>
<b>(B树)从AVL树到B树</b><br><ul><li>因为AVL树每个节点的子节点最多都是左右各一个,当数据量大的时候,这种结构下树高就会一直增加,从而增加I/O次数,影响查询效率,为了解决这个问题,B树出现了,也叫<font color="#e74f4c">多路平衡查找树(Balance Tree)</font>。一个拥有3000W数据的表,主键类型为int或bigint,主键索引树的高度大概在3~5之间。</li></ul><br><b>特征</b><br><ul><li><font color="#e74f4c">非叶节点</font>中都存储着三个元素:索引值、数据、子节点指针</li><li><font color="#e74f4c">叶节点</font>只保存索引和数据</li><li>每个节点都是唯一的,叶节点没有指针指向相邻节点</li><li>可能在非叶节点就拿到搜索记录的指针,<font color="#e74f4c">搜索效率不稳定</font></li></ul><br><b>问题</b><br><ul><li>因为非叶节点存储索引+数据,所以<font color="#e74f4c">每页存储的数量减少</font>,导致<font color="#e74f4c">树高增加</font>,从而增加了查询时的磁盘I/O,降低了查找效率。</li></ul><br><b>结构图,模拟查找29<br></b><ol><li>根据根节点找到磁盘块1,读入内存。【第一次磁盘I/O】</li><li>比较29在区间(17、35),找到磁盘块1的指针P2</li><li>根据P2指针找到磁盘块3,读入内存。【第二次磁盘I/O】</li><li>比较29在区间(26、30),找到磁盘块3的指针P2</li><li>根据P2指针找到磁盘块8,读入内存。【第三次磁盘I/O】</li><li>最终在磁盘块8中找到29</li></ol>
<b>B+树</b><br><ul><li><font color="#e74f4c">增强版多路平衡查找树</font>,InnoDB默认。</li></ul><br><b>特征</b><br><ol><li><font color="#e74f4c">主键索引树</font>的叶节点存放索引、数据、指针,且叶节点是一个<font color="#e74f4c">排好序的链表结构</font>。</li><li><font color="#e74f4c">非主键索引树</font>的叶节点不存放数据,而是存放主键索引,<font color="#e74f4c">需要回表</font>查询具体数据。</li><li><font color="#e74f4c">非叶节点</font>只保存索引和指针,这样可以有更多空间存储元素,降低B+树高度。</li><li>每个叶节点都<font color="#e74f4c">存有相邻叶节点的指针</font>,提高区间查询效率,且都是升序排列。</li><li>每次查找都会到叶节点,<font color="#e74f4c">查询效率稳定</font>。</li></ol>
Explain执行计划<br><ul><li>id<br>id表示执行select查询语句的序号,它是sql执行的顺序的标识,sql按照id从大到小执行,id相同的为一组,从上到下执行。<br></li><li><font color="#e74f4c">select_type</font><br>查询的类型,比如简单查询(SIMPLE)、联合查询(UNION)、子查询(SUBQUERY)等。</li><li>table<br>表示 explain 的一行正在访问哪个表</li><li><span style="font-size:inherit;"><font color="#e74f4c">type</font><br>表示MySQL如何找到所需行的方式,比如全表扫描(ALL)、索引扫描(index)、范围查找(range)等。<br></span>system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL</li><li><span style="font-size:inherit;"><font color="#e74f4c">possible_keys</font><br></span>MySQL认为执行查询时可能会使用的索引。</li><li><font color="#e74f4c">key</font><br>实际用到的索引,如果没有使用索引,则为NULL。</li><li><font color="#e74f4c">key_len<br></font>实际使用到的索引长度(字节数),用于判断是否充分利用索引(值越大越好),主要针对联合索引。</li><li>ref<br>当使用索引列等值查询时,与索引列进行等值匹配的对象信息。</li><li><font color="#e74f4c">rows<br></font>估算找到匹配的记录所需要读取的行数(值越小越好)。</li><li>filterred<br>某查询经过搜索条件过滤后剩余记录条数的百分比</li><li><font color="#e74f4c">Extra<br></font>Using index:表示查询的列被<font color="#e74f4c">索引覆盖</font><span style="font-size:inherit;">,是</span><font color="#e74f4c">查询性能比较高的体现</font><span style="font-size:inherit;">,即所要查询的信息搜在索引里面可以得到,<font color="#e74f4c">不用回表</font>,索引被正确使用。<br></span>Using where:与Using index相反,查询的列并<font color="#e74f4c">没有被索引覆盖</font><span style="font-size:inherit;">,where条件后面使用的是非索引的前导列,仅使用了where条件而已。<br></span>Using temporary:表示需要使用<font color="#e74f4c">临时表</font><span style="font-size:inherit;">来存储结果集,常见于排序和分组查询。<br></span>Using filesort:<font color="#e74f4c">“文件排序”</font><span style="font-size:inherit;">,指某些排序无法使用索引,只能在内存(记录较少时)或磁盘中(记录较多时)进行排序,效率低。<br></span>Using join buffer:表示在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。</li></ul>
<b>表字段设计</b><br><ul><li>字段类型优先级<br>整型 > date/time > enum char > varchar > blob,text<br><br></li><li>可以选择整型就不选字符型<br>1、整型是定长的,没有国家地区之分,没有字符集差异。<br>2、tinyint和char(1)从空间上看都是1字节,但order by排序tinyint快一些,因为字符需要考虑字符集与校对集。<br>3、若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销,因为在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。<br><br></li><li>避免字段可为NULL<br>1、NULL列需要行中的额外空间来记录它们的值是否为NULL。<br>2、如果允许为NULL,就要为每条数据多分配1个字节的空间来表示字段是否为NULL。<br>3、空字符串''是不占用磁盘空间的(它的长度是0字节所以不占用)。<br>4、SQL语句中对空字符串进行判断时可以使用=、>、<符号;但是对NULL进行判断时必须使用is null或is not null(会导致索引失效)。<br>5、使用count(*)会计算所有行,但count(column_name)会过滤掉NULL值,不会过滤掉空字符串。<br><br></li><li>char与varchar<br>1、char长度固定,当存入的数据长度<定义的长度时会用空格来填充剩余部分,当<font color="#e74f4c">查询时会删除这些空格</font>返回,速度更快,适合存储短字符串,或值长度都接近的数据,如密码。<br>3、varchar可变长度,保存时会保留尾部空格,并在<font color="#e74f4c">查询时返回</font>,相对更占空间,适合存储较长字符串,或值长度不一。</li></ul>
事务
<b>事务特性</b><br><ul><li>A:原子性(undolog)<br>一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。</li><li>C:一致性(undolog+redolog)<br>在事务开始之前和事务结束以后,数据库的完整性没有被破坏,多个事务对同一个数据读取的结果是相同的。<br></li><li>I:隔离性(MVCC+锁)<br>数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。</li><li>D:持久性(redolog)<br>一个事务被提交后,对数据的修改就是永久的,即便系统故障也不会丢失。</li></ul>
<b>事务问题</b><br><ul><li>脏读(Dirty read)<br>事务A读取到事务B<font color="#e74f4c">未提交的数据</font>就是脏读。<br>事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据。</li><li>不可重复读(Unrepeatableread)<br>事务A前后<font color="#e74f4c">多次读取同一字段数据</font>,<font color="#e74f4c">前后结果不一致</font>的现象称为不可重复读。<br>事务A多次读取同一数据,事务B在事务A多次读取的过程中对数据作了更新并提交,导致事务A多次读取同一数据不一致。</li><li>幻读(Phantom read)<br>事务A前后<font color="#e74f4c">多次读取同一结果集</font>,<font color="#e74f4c">前后结果集不一致</font>的现象称为幻读。<br>事务A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是事务B就在这个时候插入了一条分数为98的新记录,当事务A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。<br>select某记录是否存在?不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。<br>幻读和不可重复读类似,<font color="#e74f4c">幻读强调的是数据集合的增减,而不是单个字段的变更</font></li><li>丢失修改(Lost to modify)<br>指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据,这样第一个事务内的修改结果就被丢失,因此称为丢失修改。<br>事务A读取表中的数据age=20,事务B也读取age=20,事务A修改age=age-1,事务B也修改age=age-1,最终结果age=19,事务A的修改被丢失。</li></ul>
<b>事务隔离级别</b><br><ul><li>Read uncommitted(读未提交)<br>事务中的修改,即使没有提交,对其他事务也都是可见的,解决了丢失修改,但还是可能会出现脏读。</li><li>Read committed(读已提交)<br>事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的,解决了丢失修改和脏读问题,会导致不可重复读。</li><li><font color="#e74f4c">(默认)Repeatable read(可重复读)<br></font>在一个事务内,多次读同一个数据,在这个事务还没结束时,其他事务不能修改该数据,这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别。<br>读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务(包括了读写),这样避免了不可重复读和脏读,但是有时可能会出现幻读。(读取数据的事务)可以通过“共享读镜”和“排他写锁”实现。解决了丢失修改、脏读、不可重复读、但是还会出现幻读。</li><li>Serializable(串行化)<br>提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。如果仅仅通过“行级锁”是无法实现序列化的,必须通过其他机制保证新插入的数据不会被执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也是最高的,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻读,解决了更新丢失、脏读、不可重复读、幻读(虚读)。</li></ul>
<b>事务提交<br></b><ul><li>显式提交<br>用COMMIT命令直接完成的提交为显式提交。</li><li>隐式提交<br>用SQL命令间接完成的提交为隐式提交。这些命令是:ALTER,AUDIT,COMMENT,CONNECT,CREATE,DISCONNECT,DROP,EXIT,GRANT,NOAUDIT,QUIT,REVOKE,RENAME。</li><li>自动提交<br>AUTOCOMMIT设置为ON,则在插入、修改、删除语句执行后,系统将自动进行提交。</li></ul>
锁机制
<b>表级锁(MyISAM、InnoDB)</b><br><b>特点</b>:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。<br><b>种类</b>:表级别的S锁、X锁<br><b>意向锁</b>,表明事务稍后要进行哪一种类型的锁<br><ul><li>意向共享锁(IS)<br>表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁</li><li>意向排他锁(IX)<br>类似上面,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁</li><li>插入意向锁<br>间隙锁的一种(所以,也是实施在索引上的),它是专门针对insert操作的。<br>多个事务,在同一个索引上插入记录时,如果插入的位置不冲突,不会阻塞彼此</li></ul><b>自增锁</b>:如果表中存在自增字段,MySQL便会自动维护一个自增锁。<b><br><br>行级锁(InnoDB)</b><br>select ... where ... for update<br><b>特点</b>:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。<br><b>种类</b><br><ul><li><span style="font-size:inherit;"><font color="#e74f4c">记录锁(Record Lock)</font><br></span>使用唯一索引时,仅锁定一行记录。</li><li><font color="#e74f4c">间隙锁(Gap Lock)</font><br>锁定一个范围,但不包括记录本身。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的情况(隔离级别为可重复读时才生效)。</li><li><font color="#e74f4c">(默认)临建锁(Next key Lock)</font><br>记录锁 + 间隙锁,锁定一个范围,并且锁定记录本身,主要目的是解决幻读的问题。<br>1、当InnoDB扫描索引记录的时候,会首先对索引记录加上行锁(Record Lock)<br>2、再对索引记录两边的间隙加上间隙锁(Gap Lock)。 加上间隙锁之后,其他事务就不能在这个间隙修改或者插入记录。<br>3、当查询的索引含有唯一属性(唯一索引,主键索引)时,Innodb存储引擎会对next-key lock进行优化,将其降为record lock,即仅锁住索引本身,而不是范围。</li></ul><b>场景说明</b>:字段a:主键唯一索引,字段b:普通索引,字段c:无索引<br><ul><li>主键索引<br>select a,b,c from table where a=1 for update;<br>1、a字段存在1的记录:从临建锁变为记录锁<br>2、a字段不存在1的记录:临建锁变为间隙锁,锁定区间(1前面一个值到1后面一个值)</li><li>普通索引<br>select a,b,c from table where b=1 for update;<br>1、b字段存在1的记录:临建锁变为间隙锁,锁定区间(1前面一个值到1后面一个值)</li></ul>
MVCC(多版本并发控制)
MVCC是一种用于InnoDB引擎<font color="#e74f4c">提高数据库并发性能的技术</font>,它允许在不锁定整个表的情况下执行读取操作,从而减少了读写操作之间的冲突。<br><ul><li>通过<font color="#e74f4c">行记录隐式字</font><font color="#f44336">段+undolog+readView<b>实现快照读</b>,解决读写操作冲突,实现非阻塞读。</font></li><li>通过版本号(版本链),避免同一数据在不同事务间竞争。</li></ul>
<b>当前读<br></b><ul><li>读取的是记录最新版本(最新数据,而不是历史版本的数据),<font color="#e74f4c">读取时会对记录加锁</font>来保证并发事务不能修改当前记录。select ... lock in share mode(共享锁)、select ... for update、update、insert、delete(排他锁)都是一种当前读。</li></ul><br><b>快照读<br></b><ul><li>简单的select(不加锁)就是快照读,读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。<br>Read Committed:每次select都生成一个快照读。<br>Repeatable Read:开启事务后第一个select语句才是快照读的地方。<br>Serializable:快照读会退化成当前读。</li></ul>
主要依赖<br>
<b>三个隐藏字段<br></b><ul><li>DB_TRX_ID:最近修改本行记录的<font color="#e74f4c">事务ID</font>,也就是插入、修改该记录的事务ID。</li><li>DB_ROLL_RTR:指向undo log的<font color="#e74f4c">回滚指针</font>,该记录的一个版本。</li><li>DB_ROW_ID:<font color="#e74f4c">隐式主键</font>,如果表中没有定义主键,将生成该字段作为主键。</li></ul>
<b>undo log<br></b><ul><li>不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,(头插法)链表的头部是较新的旧记录,链表尾部是较早的记录。</li></ul>
readView
<b>(readView)读视图</b>是<font color="#e74f4c">快照读</font>SQL执行时MVCC提取数据的依据,记录并维护系统当前活跃的事务ID(未提交事务)。<br><ul><li><span style="font-size:inherit;">主要字段<br></span>m_ids:当前活跃的事务ID集合。<br>min_trx_id:最小活跃事务ID。<br>max_trx_id:预分配事务ID,当前最大事务ID+1(事务ID是自增的)。<br>creator_trx_id:ReadView创建者的事务ID。</li></ul>
版本链数据访问规则
RC实现原理
RR实现原理
分库分表
实施策略
分库
垂直拆分
将库中的表根据业务类型拆分到多个库
水平拆分
将库中表数据按一定策略拆分到多个库
分表
垂直拆分
将表按字段的业务类型拆分到多个表
水平拆分
将表中的数据按一定策略拆分到多个表
主从复制
概述
MySQL支持一台主库同时向多台从库进行复制,从库同时也可以作为其他从服务器的主库,实现链状复制<br>
主库出现问题,可以快速切换到从库提供服务
实现读写分离,降低单台数据库访问压力
可以在从库中执行备份,以避免备份期间影响主库服务
原理
三个线程
(主库)binlog dump thread
(从库)I/O thread
(从库)SQL thread
步骤
1、主库执行DDL和DML操作,按照修改顺序依次写入bin log<br>2、从库I/O线程连接上主库并请求读取指定位置position的日志内容<br>3、主库收到请求后,将指定位置position之后的日志内容、主库bin log文件名称以及在日志中的位置推送给从库<br>4、从库I/O线程收到数据后,将日志内容依次写入relay log文件最末端,并将bin log文件名和位置position记录到master-info文件中,以便下次使用。<br>5、从库的SQL线程检测到relay log中内容更新后,读取日志并解析成可执行的sql语句进行重放
全同步复制
主库写入binlog后强制同步日志到从库,所有从库都执行完后才返回,这种方式对性能影响很大
半同步复制
从库写入日志成功后返回ACK给主库,主库收到至少一个从库的确认就认为完成
组件<br>
Mycat
基于Java编写的MySQL数据库中间件,可以像使用MySQL一样使用Mycat
ShardingJDBC
基于Java的AOP,在应用程序中对本地执行的SQL进行拦截等操作,需要自行编码配置实现
分支主题
逻辑存储结构
<b>日志</b><br><ul><li>(物理日志)重写日志:redo log<br><font color="#e74f4c">记录数据被修改后的信息</font><span style="font-size:inherit;">,当数据操作中途发生故障,可以利用该日志重做,保证持久性。<br></span>InnoDB存储引擎独有的,它让MySQL拥有了崩溃恢复能力。<br>默认开启,show variables like '%innodb_log%';查看是否开启和存放位置。<br><br></li><li>(逻辑日志)回滚日志:undo log<br><font color="#e74f4c">记录数据被修改前的信息</font><span style="font-size:inherit;">,为了在发生错误时可以回滚到之前的操作。<br></span>默认关闭,show variables like '%innodb_undo%';查看是否开启和存放位置。<br><br></li><li>(逻辑日志)二进制日志:bin log<br><font color="#e74f4c">记录数据增、删、改操作的信息</font><span style="font-size:inherit;">,主要作用是用于数据库的主从复制及数据的增量恢复。<br></span>与redo log相辅相成,共同保证事务持久性。<br>采用追加的方式写入,二进制形式存储在磁盘中。<br>默认关闭,show variables like '%log_bin%';查看是否开启和存放位置。<br><br></li><li>中继日志:relay log<br><font color="#e74f4c">用于主从复制</font><span style="font-size:inherit;">,从数据库I/O线程将主数据的二进制日志(bin log)读取过来记录到从数据库本地reay log,然后从数据库SQL线程会读取relay log日志的内容并应用到从数据库,从而使从数据库和主数据库的数据保持一致。<br></span>一般情况下它在MySQL主从同步读写分离集群的从节点才开启。主节点一般不需要这个日志。<br>默认关闭,show variables like '%relay%';查看是否开启和存放位置。<br><br></li><li>错误日志:err log<br><font color="#e74f4c">记录在启动、运行、关闭过程中的错误信息</font><span style="font-size:inherit;">。<br></span>默认开启,show variables like '%log_error%';查看是否开启和存放位置。<br><br></li><li>慢查询日志:show query log<br><font color="#e74f4c">记录执行时间超过指定阈值的SQL</font><span style="font-size:inherit;">。<br></span>默认关闭,show variables like '%log_query%';查看是否开启和存放位置。<br>show global variables like 'long_query_time';查看慢查询语句执行时间,默认10秒。<br><br></li><li>一般查询日志:general log<br><font color="#e74f4c">记录客户端连接信息、增删改查SQL信息</font><span style="font-size:inherit;">。<br></span>默认关闭,一般不建议开启。</li></ul>
<b>范式</b><br><ul><li>第一范式:每个列都不可以再拆分。</li><li>第二范式:在第一范式的基础上,每个表只有一个主键。</li><li>第三范式:在第二范式的基础上,非主键列只依赖于主键,不依赖于其他非主键。</li><li>适当的增加冗余字段,提高查询效率</li></ul>
<b>关系型数据库<br></b><ul><li>Oracle、MySQL、SQL Server、Microsoft Access、DB2 等。</li><li>关系型数据库是一个<font color="#e74f4c">结构化的数据库</font>,创建在关系模型(二维表格模型)基础上,一般<font color="#e74f4c">面向记录</font>。</li><li>实例–>数据库–>表(table)–>记录行(row)、数据字段(column)。<br><br></li><li>优点<br>容易理解:二维表的结构非常贴近现实世界,二维表格,容易理解。<br>使用方便:通用的SQL语句使得操作关系型数据库非常方便。<br>易于维护:数据库的ACID特性,大大降低了数据冗余和数据不一致的概率。<br><br></li><li>缺点<br>海量数据的读写性能比较差。<br>固定的表结构,可扩展性不够。<br>高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈。</li></ul>
<b>非关系型数据库</b><br><ul><li>Redis、MongBD、Hbase、CouhDB 等。</li><li>除了主流的关系型数据库外的数据库,都认为是非关系型。</li><li>非关系型数据库不需要手动建数据库和集合(表)。</li><li>实例–>数据库–>集合(collection)–>键值对(key-value)。<br><br></li><li>优点<br>格式灵活:存储数据的格式可以是key:value形式、文档形式、图片形式等等,使用灵活,应用场景广泛。<br>速度快:主要使用内存作为载体。<br>高扩展性:面向可拓展的分布式数据库。<br><br></li><li>缺点<br>不能够像sql那样提供where字段属性的查询。<br>适合存储较为简单的数据。<br>有一些不能够持久化数据,所以需要和关系型数据库结合。</li></ul>
<b>SQL语言<br></b><ul><li>数据查询语言(DQL):SELECT</li><li>数据操纵语言(DML):INSERT、UPDATE、DELETE</li><li>数据定义语言(DDL):CREATE TABLE / VIEW / INDEX / SYN / CLUSTER</li><li>数据控制语言(DCL):GRANT、ROLLBACK [WORK] TO [SAVEPOINT]、COMMIT [WORK]</li></ul>
<b>扩展</b><br><ul><li><b>My</b><span style="font-size:inherit;">SQL中字符类型转换问题<br></span><font color="#569230">select 'a'=0;,返回1,条件成立。<br></font><font color="#a6a6a6">select 'b'=1;,返回0,条件不成立(b与数字1比较,存在隐式类型转换,也不会走索引)。<br></font><font color="#569230">select '123'=123;,返回1,条件成立。<br></font>非数字字符会转换成0,数字字符会原样转换成数值类型。<br><br></li><li><span style="font-size:inherit;">为什么建议InnoDB必须建立主键索引?<br></span>1、提升查询效率。<br>2、如果没有主键索引,Mysql默认也会维护一个RowId作为隐藏主键,增加维护成本。<br><br></li><li>为什么推荐整型自增主键?<br>1、占用空间小且便于索引排序。<br>2、索引维护成本小,直接加入叶节点尾部即可,非自增主键会频繁导致叶节点分裂。<br><br></li><li>回表<br><font color="#e74f4c">从非主键索引树搜索回到主键索引树搜索的过程</font>。<br><br></li><li>索引覆盖<br><font color="#e74f4c">从非主键索引树就能查到的记录,无需回表</font>。<br><br></li><li>MyISAM为什么比InnoDB快?<br>并不是完全意义上的快,也要看实际场景,一般情况下InnoDB在select时要维护的东西比MyISAM多。<br>数据块,InnoDB要缓存,MyISAM只缓存索引块。<br>InnoDB寻址要映射到块,再到行,MyISAM记录的直接是文件的Offset,定位更快。<br>InnoDB还要维护MVCC多版本并发控制。</li></ul><font color="#569230"></font>
<b>存储引擎(作用于表)</b><br><ul><li>MyISAM<br><font color="#e74f4c">不支持主键,不支持事务,不支持行锁,适用读多写少业务</font>。<br><font color="#e74f4c">表锁</font>,即使操作一条数据也会锁住整张表,不适合高并发的操作。<br>查询表的总行数无需全表扫描,总行数存储在一个变量中。<br><font color="#e74f4c">非聚簇索引</font>:主键索引树的叶节点中不存放数据,仅存放索引和数据在磁盘的位置,需要从磁盘文件查询实际数据。<br><br></li><li>InnoDB(5.5.5版本后默认)<br><font color="#e74f4c">支持主键,支持事务,支持表锁行锁,适用写多读少业务</font>。<br><font color="#e74f4c">行锁</font>,操作时只锁定某一行,不对其他行有影响,适合高并发操作。<br>查询表的总行数会全表扫描。<br><font color="#e74f4c">聚簇索引</font>:主键索引树的叶节点会存放数据和索引,无需回表。<br><br></li><li>Memory引擎<br>存储在内存中。<br><br></li><li>Archive引擎<br>只支持INSERT和SELECT操作。<br><br></li><li>CSV引擎<br>基于CSV文件,不支持索引,一般用于数据迁移。</li></ul>
Collect
Get Started
Collect
Get Started
Collect
Get Started
Collect
Get Started
评论
0 条评论
下一页