Java面试问题整理笔记-MySQL基础知识

MySQL基础知识

0.数据库设计通常分为哪几步?

  1. 需求分析 : 分析用户的需求,包括数据、功能和性能需求。
  2. 概念结构设计 : 主要采用 E-R 模型进行设计,包括画 E-R 图。
  3. 逻辑结构设计 : 通过将 E-R 图转换成表,实现从 E-R 模型到关系模型的转换。
  4. 物理结构设计 : 主要是为所设计的数据库选择合适的存储结构和存取路径。
  5. 数据库实施 : 包括编程、测试和试运行
  6. 数据库的运行和维护 : 系统的运行与数据库的日常维护。

1.MySQL 中有哪几种锁?

1.1表级锁

开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。

1.2行级锁

开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

1.3页面锁

开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般

2.SQL优化

2.1Sql优化意见

  • 查询语句中不要使用select *
  • 尽量减少子查询,使用关联查询(left join,right join,inner join)替代
  • 减少使用IN或者NOT IN ,使用exists,not exists或者关联查询语句替代
  • or 的查询尽量用 union或者union all 代替(在确认没有重复数据或者不用剔除重复数据时,union
    all会更好)
  • 应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
  • 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0
  • 应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描
  • Where 子句中:where 表之间的连接必须写在其他 Where 条件之前,那些可以过滤掉最大数量记录的条件必须写在 Where 子句的末尾.HAVING 最后。
  • 避免在索引列上使用 IS NULL 和 IS NOT NULL
  • 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

2.2对 SQL 慢查询会考虑哪些优化 ?

  • 分析语句, 是否加载了不必要的字段/数据。
  • 分析 SQL 执行计划( explain extended) , 思考可能的优化点, 是否命中索引等。
  • 查看 SQL 涉及的表结构和索引信息。
  • 如果 SQL 很复杂, 优化 SQL 结构。
  • 按照可能的优化点执行表结构变更、 增加索引、 SQL 改写等操作。
  • 查看优化后的执行时间和执行计划。
  • 如果表数据量太大, 考虑分表。
  • 利用缓存, 减少查询次数

3.简单说一说drop、delete与truncate的区别

SQL中的drop、delete、truncate都表示删除,但是三者有一些差别

  • delete:仅删除表数据,支持条件过滤,支持回滚。记录日志。因此比较慢。

  • truncate:仅删除所有数据,不支持条件过滤,不支持回滚。不记录日志,效率高于delete。

  • drop:删除表数据同时删除表结构。将表所占的空间都释放掉。删除效率最高。

  • delete和truncate只删除表的数据不删除表的结构

  • 速度,一般来说: drop> truncate >delete

  • delete语句是dml(Data Manipulation Language, DML),这个操作会放到rollback segement中,事务提交之后才生效;

  • 如果有相应的trigger,执行的时候将被触发. truncate,drop是ddl(Data Definition Language), 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger.

4数据库是事务

事务(TRANSACTION)是作为单个逻辑工作单元执行的一系列操作, 这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行 。 事务是一个不可分割的工作逻辑单元事务必须具备以下四个属性,简称 ACID 属性:

4.1原子性(Atomicity)

事务是一个完整的操作。事务的各步操作是不可分的(原子的);要么都执行,要么都不执行

4.2一致性(Consistency)

事务完成时,数据必须处于一致状态。

4.3隔离性(Isolation)

对数据进行修改的所有并发事务是彼此隔离的, 这表明事务必须是独立的,它不应以任何方式依赖于或影响其他事务。

4.4永久性(Durability)

事务完成后,它对数据库的修改被永久保持,事务日志能够保持事务的永久性。

5.事务隔离级别有哪些?MySQL的默认隔离级别是?

5.1READ-UNCOMMITTED(读取未提交)

最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读幻读不可重复读

5.2READ-COMMITTED(读取已提交)

允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读不可重复读仍有可能发生。

5.3REPEATABLE-READ(可重复读)

对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

5.4SERIALIZABLE(可串行化)

最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。

6.mysql有哪些数据类型

6.1整数类型

请添加图片描述

包括TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,分别表示1字节、2字节、3字节、4字节、8字节整数。任何整数类型都可以加上UNSIGNED属性,表示数据是无符号的,即非负整数。
长度:整数类型可以被指定长度,例如:INT(11)表示长度为11的INT类型。长度在大多数场景是没有意
义的,它不会限制值的合法范围,只会影响显示字符的个数,而且需要和UNSIGNED ZEROFILL属性配
合使用才有意义。
例子,假定类型设定为INT(5),属性为UNSIGNED ZEROFILL,如果用户插入的数据为12的话,那么数
据库实际存储数据为00012。

6.2实数类型

包括FLOAT、DOUBLE、DECIMAL。

  • DECIMAL可以用于存储比BIGINT还大的整型,能存储精确的小数。
  • 而FLOAT和DOUBLE是有取值范围的,并支持使用标准的浮点进行近似计算。
  • 计算时FLOAT和DOUBLE相比DECIMAL效率更高一些,DECIMAL你可以理解成是用字符串进行处理。

6.3字符串类型

包括VARCHAR、CHAR、TEXT、BLOB

  • VARCHAR用于存储可变长字符串,它比定长类型更节省空间。VARCHAR使用额外1或2个字节存储字符串长度。列长度小于255字节时,使用1字节表示,否则使用2字节表示。VARCHAR存储的内容超出设置的长度时,内容会被截断。
  • CHAR是定长的,根据定义的字符串长度分配足够的空间。CHAR会根据需要使用空格进行填充方便比较。CHAR适合存储很短的字符串,或者所有值都接近同一个长度。CHAR存储的内容超出设置的长度时,内容同样会被截断。
  • 使用策略:
    对于经常变更的数据来说,CHAR比VARCHAR更好,因为CHAR不容易产生碎片。
    对于非常短的列,CHAR比VARCHAR在存储空间上更有效率。
    使用时要注意只分配需要的空间,更长的列排序时会消耗更多内存。
    尽量避免使用TEXT/BLOB类型,查询时会使用临时表,导致严重的性能开销。

6.4枚举类型(ENUM)

把不重复的数据存储为一个预定义的集合。有时可以使用ENUM代替常用的字符串类型。ENUM存储非常紧凑,会把列表值压缩到一个或两个字节。ENUM在内部存储时,其实存的是整数。尽量避免使用数字作为ENUM枚举的常量,因为容易混乱。排序是按照内部存储的整数

6.5日期和时间类型

尽量使用timestamp,空间效率高于datetime,用整数保存时间戳通常不方便处理。如果需要存储微妙,可以使用bigint存储。看到这里,这道真题是不是就比较容易回答了

7.什么是索引?

  • 索引是一种特殊的文件(InnoDB 数据表上的索引是表空间的一个组成部分), 它们包含着对数据表里所有记录的引用指针。

  • 索引是一种数据结构。 数据库索引, 是数据库管理系统中一个排序的数据结构, 以协助快速查询、 更新数据库表中数据。 索引的实现通常使用 B 树及其变种 B+树。

  • 更通俗的说, 索引就相当于目录。 为了方便查找书中的内容, 通过对内容建立索引形成目录。 索引是一个文件, 它是要占据物理空间的。

  • 在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。

8.MySQL索引底层

8.1BTree索引哈希索引

  • 对于哈希索引来说,底层的数据结构就是哈希表,进行查找时,调用一次hash函数就可以获取到相应的键值,之后进行回表查询获得实际数据.因此在绝⼤多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;其余⼤部分场景,建议选择BTree索引。

  • hash索引进行等值查询更快(一般情况下),但是却无法进行范围查询.因为在hash索引中经过hash函数建立索引之后,索引的顺序与原顺序无法保持一致,不能支持范围查询.

  • 而B+树的的所有节点皆遵循(左节点小于父节点,右节点大于父节点,多叉树也类似)天然支持范围

  • MySQL的BTree索引使⽤的是B树中的B+Tree()多路平衡查找树,对于每一次的查询都是从根节点出发,查找到叶子节点方可以获得所查键值,然后根据查询判断是否需要回表查询数据.但对于主要的两种存储引擎的实现⽅式是不同的。

  • MyISAM: B+Tree叶节点的data域存放的是数据记录的地址。在索引检索的时候,⾸先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其 data 域的值,然后以 data 域的值为地址读取相应的数据记录。这被称为==“⾮聚簇索引”==。

  • InnoDB: 其数据⽂件本身就是索引⽂件。相⽐MyISAM,索引⽂件和数据⽂件是分离的,其表数据⽂件本身就是按B+Tree组织的⼀个索引结构,树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据⽂件本身就是主索引。这被称为==“聚簇索引(或聚集索引)== ”。⽽其余的索引都作为辅助索引,辅助索引的data域存储相应记录主键的值⽽不是地址,这也是和MyISAM不同的地⽅。在根据主索引搜索时,直接找到key所在的节点即可取出数据;在根据辅助索引查找时,则需要先取出主键的值,再⾛⼀遍主索引。 因此,在设计表的时候,不建议使⽤过⻓的字段作为主键,也不建议使⽤⾮单调的字段作为主键,这样会造成主索引频繁分裂。

  • hash索引不支持模糊查询以及多列索引的最左前缀匹配.原理也是因为hash函数的不可预测.AAAA和AAAAB的索引没有相关性

  • hash索引任何时候都避免不了回表查询数据,而B+树在符合某些条件(聚簇索引,覆盖索引)的时候可以只通过索引完成查询.

  • hash索引虽然在等值查询上较快,但是不稳定.性能不可预测,当某个键值存在大量重复的时候,发生hash碰撞,此时效率可能极差.而B+树的查询效率比较稳定,对于所有的查询都是从根节点到叶子节点,且树的高度较低.因此,在大多数情况下,直接选择B+树索引可以获得稳定且较好的查询速度.而不需要使用hash索引.

8.2什么是回表?

在普通索引查到主键索引后,再去主键索引定位记录。等于说非主键索引需要多走一个索引树。

8.3如何避免回表?

索引覆盖被查询的字段。

8.4什么是索引覆盖

如果一个索引包含(或覆盖)所有需要查询的字段的值,称为‘覆盖索引’。

9.索引类型

9.1主键索引

数据列不允许重复, 不允许为 NULL, 一个表只能有一个主键。

主键,是一种特殊的唯一索引,在一张表中只能定义一个主键索引,主键用于唯一标识一条记录,使用关键字PRIMARY KEY来创建

9.2唯一索引

数据列不允许重复, 允许为 NULL 值, 一个表允许多个列创建唯一索引。 如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字 UNIQUE把它定义为一个唯一索引。也就是说,唯一索引可以保证数据记录的唯一性。

  • 可以通过ALTER TABLE table_name ADD UNIQUE (column);创建唯一索引。
  • 可以通过 ALTER TABLE table_name ADD UNIQUE (column1,column2); 创建唯一组合索引

9.3普通索引

基本的索引类型, 没有唯一性的限制, 允许为 NULL 值。普通索引(由关键字 KEY 或 INDEX 定义的索引)的唯一任务是加快对数据的访问速度。

  • 可以通过 ALTER TABLE table_name ADD INDEX index_name (column);创建普通索引
  • 可以通过 ALTER TABLE table_name ADD INDEX index_name(column1,column2, column3);创建组合索引。

9.4 全文索引

是目前搜索引擎使用的一种关键技术。

  • 可以通过 ALTER TABLE table_name ADD FUL LTEXT (column);创建全文索引

9.5联合索引是什么?为什么需要注意联合索引中的顺序?

MySQL可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要
按照建立索引时的字段顺序挨个使用,否则无法命中索引。

具体原因为:
MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为:先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序。

当进行查询时,此时索引仅仅按照name严格有序,因此必须首先使用name字段进行等值查询,之后对于匹配到的列而言,其按照age字段严格有序,此时可以使用age字段用做索引查找,以此类推。因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面。此外可以根据特例的查询或者表结构进行单独的调整

10.创建索引时需要注意什么?

10.1非空字段

应该指定列为 NOT NULL, 除非你想存储 NULL。 在 mysql 中, 含有空值的列很难进行查询优化, 因为它们使得索引、 索引的统计信息以及比较运算更加复杂。 应该用 0、 一个特殊的值或者一个空串代替空值

10.2取值离散大的字段

( 变量各个取值之间的差异程度) 的列放到联合索引的前面, 可以通过 count()函数查看字段的差异值,返回值越大说明字段的唯一值越多字段的离散程度高;

10.3 索引字段越小越好

数据库的数据存储以页为单位一页存储的数据越多,一次 IO 操作获取的数据越大效率越高。

11.使用索引查询一定能提高查询的性能吗? 为什么

11.1索引查询一定能提高查询的性能吗

通常, 通过索引查询数据比全表扫描要快。 但是我们也必须注意到它的代价。索引需要空间来存储, 也需要定期维护, 每当有记录在表中增减或索引列被修改时, 索引本身也会被修改。 这意味着每条记录的 INSERT, DELETE, UPDATE 将为此多付出 4, 5次的磁盘 I/O。 因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢。 使用索引查询不一定能提高查询性能, 索引范围查询(INDEX RANGE SCAN)适用于两种情况:

  • 基于一个范围的检索, 一般查询返回结果集小于表中记录数的 30%
  • 基于非唯一性索引的检索

11.2索引不生效的情况?

  • 使用不等于查询
  • NULL值
  • 列参与了数学运算或者函数
  • 在字符串like时左边是通配符.比如%xxx
  • 当mysql分析全表扫描比使用索引快的时候不使用索引.
  • 当使用联合索引,前面一个条件为范围查询,后面的即使符合最左前缀原则,也无法使用索引.

12.什么是聚簇索引? 何时使用聚簇索引与非聚簇索引

12.1聚簇索引

数据存储与索引放到了一块, 找到索引也就找到了数据

12.2非聚簇索引

数据存储于索引分开结构, 索引结构的叶子节点指向了数据的对应行,myisam 通过 key_buffer 把索引先缓存到内存中, 当需要访问数据时( 通过索引访问数据) , 在内存中直接搜索索引, 然后通过索引找到磁盘相应数据, 这也就是为什么索引不在 key buffer 命中时, 速度慢的原因

13.MVCC 是什么? 它的底层原理是什么?

13.1MVCC, 多版本并发控制

MVCC, 多版本并发控制,它是通过读取历史版本的数据, 来降低并发事务冲突, 从而提高并发性能的一种机制。指的是一种提高并发的技术。最早的数据库系统,只有读读之间可以并发,读写,写读,写写都要阻塞。引入多版本之后,只有写写之间相互阻塞,其他三种操作都可以并行,这样大幅度提高了InnoDB的并发度。

MVCC全称是多版本并发控制系统,InnoDB的MVCC是通过在每行记录后面保存两个隐藏的列来实现,这两个列一个保存了行的创建时间一个保存行的过期时间(删除时间)。当然存储的并不是真实的时间而是系统版本号(system version number)每开始一个新的事务,系统版本号都会自动新增,事务开始时刻的系统版本号会作为事务的版本号,用来查询到每行记录的版本号进行比较。

  • 事务版本号
  • 表的隐藏列:每行记录除了我们自定义的字段外,还有数据库隐式定义的DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID等字段
  • undo log:undolog被称之为回滚日志,表示在进行insert,delete,update操作的时候产生的,方便回滚的日志。
  • read view :Read View是事务进行快照读操作的时候生产的读视图,在该事务执行快照读的那一刻,会生成一个数据系统当前的快照,记录并维护系统当前活跃事务的id,事务的id值是递增的。其实Read View的最大作用是用来做可见性判断的,也就是说当某个事务在执行快照读的时候,对该记录创建一个Read View的视图,把它当作条件去判断当前事务能够看到哪个版本的数据,有可能读取到的是最新的数据,也有可能读取的是当前行记录的undolog中某个版本的数据。

13.2 MVCC可以为数据库解决以下问题

  • 在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能。
  • 解决脏读、幻读、不可重复读等事务隔离问题,但是不能解决更新丢失问题。

13.3MVCC实现原理

mvcc的实现原理主要依赖于记录中的三个隐藏字段,undolog,read view来实现的。

14.分库分表之后,id 主键如何处理?

因为要是分成多个表之后,每个表都是从 1 开始累加,这样是不对的,我们需要一个全局唯一的 id 来支持。
生成全局 id 有下面这几种方式:

14.1UUID

不适合作为主键,因为太长了,并且无序不可读,查询效率低。比较适合用于生成唯一的名字的标示比如文件的名字。

好处就是本地生成,不要基于数据库来了;不好之处就是,UUID 太长了、占用空间大,作为主键性能太差了;更重要的是,UUID 不具有有序性,会导致 B+ 树索引在写的时候有过多的随机写操作(连续的 ID 可以产生部分顺序写),还有,由于在写的时候不能产生有顺序的append 操作,而需要进行 insert 操作,将会读取整个 B+ 树节点到内存,在插入这条记录后会将整个节点写回磁盘,这种操作在记录占用空间比较大的情况下,性能下降明显。

适合的场景:如果你是要随机生成个什么文件名、编号之类的,你可以用 UUID,但是作为主键
是不能用 UUID 的

14.2数据库自增 id

两台数据库分别设置不同步长,生成不重复ID的策略来实现高可用。这种方式生成的 id 有序,但是需要独立部署数据库实例,成本高,还会有性能瓶颈。

14.3利用 redis 生成 id

性能比较好,灵活方便,不依赖于数据库。但是,引入了新的组件造成系统更加复杂,可用性降低,编码更加复杂,增加了系统成本。

14.4Twitter的snowflake算法

snowflake 算法
snowflake 算法是 twitter 开源的分布式 id 生成算法,采用 Scala 语言实现,是把一个 64 位的long 型的 id,1 个 bit 是不用的,用其中的 41 bits 作为毫秒数,用 10 bits 作为工作机器 id,12bits 作为序列号。

  • 1 bit:不用,为啥呢?因为二进制里第一个 bit 为如果是 1,那么都是负数,但是我们生成的 id 都是正数,所以第一个 bit 统一都是 0。
  • 41 bits:表示的是时间戳,单位是毫秒。41 bits 可以表示的数字多达 2^41 - 1 ,也就是可以标识 2^41 - 1 个毫秒值,换算成年就是表示69年的时间。
  • 10 bits:记录工作机器 id,代表的是这个服务最多可以部署在 2^10 台机器上,也就是 1024台机器。但是 10 bits 里 5 个 bits 代表机房 id,5 个 bits 代表机器 id。意思就是最多代表2^5 个机房(32 个房),每个机房里可以代表 2^5 个机器(32台机器)。
  • 12 bits:这个是用来记录同一个毫秒内产生的不同 id,12 bits 可以代表的最大正整数是2^12 - 1 = 4096 ,也就是说可以用这个 12 bits 代表的数字来区分同一个毫秒内的4096 个不同的 id。

15什么是全局锁、共享锁、排它锁

15.1全局锁

全局锁就是对整个数据库实例加锁,它的典型使⽤场景就是做全库逻辑备份。这个命令可以使整个库处于只读状态。使⽤该命令之后,数据更新语句、数据定义语句、更新类事务的提交语句等操作都会被阻塞。

15.2共享锁⼜称读锁 (read lock)

共享锁⼜称读锁 (read lock),是读取操作创建的锁。其他⽤户可以并发读取数据,但任何事务都不能对数据进⾏修改(获取数据上的排他锁),直到已释放所有共享锁。当如果事务对读锁进⾏修改操作,很可能会造成死锁。

15.3排他锁 exclusive lock(也叫 writer lock)⼜称写锁。

若某个事物对某⼀⾏加上了排他锁,只能这个事务对其进⾏读写,在此事务结束之前,其他事务不能对其进⾏加任何锁,其他进程可以读取,不能进⾏写操作,需等待其释放。排它锁是悲观锁的⼀种实现。若事务 1 对数据对象 A 加上 X 锁,事务 1 可以读 A 也可以修改 A,其他事务不能再对 A 加任何锁,直到事物 1 释放 A 上的锁。这保证了其他事务在事物 1 释放 A 上的锁之前不能再读取和修改 A。排它锁会阻塞所有的排它锁和共享锁

16.MySQL 基础架构

请添加图片描述

从上图可以看出, MySQL 主要由下面几部分构成:

  • 连接器: 身份认证和权限相关(登录 MySQL 的时候)。
  • 查询缓存: 执行查询语句的时候,会先查询缓存(MySQL 8.0 版本后移除,因为这个功能不太实用)。
  • 分析器: 没有命中缓存的话,SQL 语句就会经过分析器,分析器说白了就是要先看你的 SQL 语句要干嘛,再检查你的 SQL 语句语法是否正确。
  • 优化器: 按照 MySQL 认为最优的方案去执行。
  • 执行器: 执行语句,然后从存储引擎返回数据。 执行语句之前会先判断是否有权限,如果没有权限的话,就会报错。
  • 插件式存储引擎 : 主要负责数据的存储和读取,采用的是插件式架构,支持 InnoDB、MyISAM、Memory 等多种存储引擎。

17.MySQL 存储引擎

MyISAM、 InnoDB、BDB、MEMORY、MERGE、EXAMPLE、NDB Cluster、ARCHIVE、CSV、BLACKHOLE、FEDERATED。

Tips:InnoDB和BDB提供事务安全表,其他存储引擎都是非事务安全表。

17.1MySQL 存储引擎 MyISAM 与 InnoDB 区别 ?

17.1.1锁粒度方面

由于锁粒度不同, InnoDB 比 MyISAM 支持更高的并发;

  • InnoDB 的锁粒度为行锁
  • MyISAM 的锁粒度为表锁、 行锁需要对每一行进行加锁, 所以锁的开销更大,但是能解决脏读和不可重复读的问题, 相对来说也更容易发生死锁

17.1.2可恢复性上

  • 由于 InnoDB 是有事务日志的, 所以在产生由于数据库崩溃等条件后, 可以根据日志文件进行恢复。
  • 而 MyISAM 则没有事务日志

17.1.3查询性能上

MylSAM 要优于 InnoDB 因为 InnoDB 在查询过程中, 是需要维护数据缓存, 而且查询过程是先定位到行所在的数据块, 然后在从数据块中定位到要查找的行;而MyISAM 可以直接定位到数据所在的内存地址, 可以直接找到数据。

17.1.4表结构文件上

  • MyISAM 的表结构文件包括:frm(表结构定义),.MYD (MYData)、.MYI (MYIndex)
  • InnoDB 的表数据文件为:ibd 和 frm(表结构定义)

17.2MyISAM 索引与 InnoDB 索引的区别?

  • InnoDB 索引是聚簇索引, MyISAM 索引是非聚簇索引。
  • InnoDB 的主键索引的叶子节点存储着行数据, 因此主键索引非常高效。
  • MyISAM 索引的叶子节点存储的是行数据地址, 需要再寻址一次才能得到数据。
  • InnoDB 非主键索引的叶子节点存储的是主键和其他带索引的列数据, 因此查询时做到覆盖索引会非常高效。

18.如何实现 MySQL 的读写分离?

其实很简单,就是基于主从复制架构,简单来说,就搞一个主库,挂多个从库,然后我们就单单只是写主库,然后主库会自动把数据给同步到从库上去。

19.MySQL 主从复制

19.1主从复制原理

主库将变更写入 binlog 日志,然后从库连接到主库之后,从库有一个 IO 线程,将主库的 binlog日志拷贝到自己本地,写入一个 relay 中继日志中。接着从库中有一个 SQL 线程会从中继日志读取 binlog,然后执行 binlog 日志中的内容,也就是在自己本地再次执行一遍 SQL,这样就可以保证自己跟主库的数据是一样的。

请添加图片描述

19.2主从复制存在问题及解决

这里有一个非常重要的一点,就是从库同步主库数据的过程是串行化的,也就是说主库上并行的操作,在从库上会串行执行。所以这就是一个非常重要的点了,由于从库从主库拷贝日志以及串行执行 SQL 的特点,在高并发场景下,从库的数据一定会比主库慢一些,是有延时的。所以经常出现,刚写入主库的数据可能是读不到的,要过几十毫秒,甚至几百毫秒才能读取到。而且这里还有另外一个问题,就是如果主库突然宕机,然后恰好数据还没同步到从库,那么有些数据可能在从库上是没有的,有些数据可能就丢失了。所以 MySQL 实际上在这一块有两个机制,一个是半同步复制,用来解决主库数据丢失问题;一个是并行复制,用来解决主从同步延时问题

  • 这个所谓半同步复制,也叫 semi-sync 复制,指的就是主库写入 binlog 日志之后,就会将强制此时立即将数据同步到从库,从库将日志写入自己本地的 relay log 之后,接着会返回一个ack 给主库,主库接收到至少一个从库的 ack 之后才会认为写操作完成了。

  • 所谓并行复制,指的是从库开启多个线程,并行读取 relay log 中不同库的日志,然后并行重放不同库的日志,这是库级别的并行


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值