Mysql基础知识:
1)事务的ACID属性:
1. 原子性(Atomicity)是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
2. 一致性(Consistency)是指事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
3. 隔离性(Isolation)是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
4. 持久性(Durability)是指一个事务一旦被提交,它对数据库中数据的改变就是永久的,接下来的其他操作和数据库故障不应该对其有任何影响。
2)对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题:
(1)脏读: 对于两个事务 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段之后,若 T2 回滚, T1读取的内容就是临时且无效的。
(2)不可重复读: 对于两个事务T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段之后,T1再次读取同一个字段, 值就不同了。
(3)幻读: 对于两个事务T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插 入了一些新的行之后,如果 T1 再次读取同一个表, 就会多出几行。
3)数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别,数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱。
4)数据库提供的 4 种事务隔离级别:
READ UNCOMMITED(读未提交), READ COMMITED(读已提交),REPEATABLE READ(可重复读),SERIALIZABLE(串行化)。上述隔离级别依次可以解决无,脏读,脏读与不可重复读,脏读,不可重复读与幻读。
5)索引介绍:
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。
在数据本身之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,这样就可以在这些数据结构上实现高级查找算法。
适合建立索引的字段是不常进行删改操作且经常查询的字段。
一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上。
我们平常所说的索引,如果没有特别指明,都是指B树(多路搜索树,并不一定是二叉树)结构组织的索引。其中聚集索引,次要索引,复合索引,前缀索引,唯一索引默认都是B+树索引,统称索引。当然,除了B+树这种类型的索引 之外,还有哈希索引 ⇒ hash index等。
6)索引优势和劣势:
优势:
类似于大学图书馆建立书目索引,提高数据检索效率,降低数据库的IO成本。
通过索引对数据进行排序,降低数据排序的成本,降低了CPU的消耗。
劣势:
索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引也是要占用空间的。
虽然索引大大提高了查询速度,同时也会降低更新表的速度,如INSERT,UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。
索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的索引。
7)索引分类:
单值索引:即一个索引只包含单个列,一个表可以有多个单列索引。
唯一索引:索引列的值必须唯一,但允许空值。
复合索引:即一个索引包含多个列。
主键索引:设定为主键后数据库会自动建立索引,innodb为聚簇索引。
8)创建索引条件:
适合创建索引的情况:
(1)主键自动建立唯一索引。
(2)查询中与其他表关联的字段,外键关系应该建立索引。
(3)频繁作为查询条件的字段应该建立索引。
(4)单值/复合索引的选择问题,高并发下倾向于创建复合索引。
(5)查询中排序字段,排序字段若通过索引去访问将大大提高排序速度。
(6)查询中同级或者分组的字段要建立索引。
不适合创建索引的情况:
(1)记录太少不需要建立索引。
(2)频繁更新的字段不适合建立索引。
(3)数据重复且分布平均的表字段不适合建立索引。
(4)where条件里用不到的字段不适合创建索引。
9)MySQL常见瓶颈:
CPU:CPU饱和时一般发生在数据装入内存或从磁盘上读取数据。
IO:磁盘I/O瓶颈发生在装入数据远大于内存容量的时候。
服务器硬件的性能瓶颈:top,free,iostat和vmstat来查看系统性能状态。
10)Explain关键字:
使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,查看MySQL是如何处理你的SQL语句的,从而得知你的查询语句或是表结构的性能瓶颈。
作用:
表的读取顺序。
数据读取操作的操作类型。
哪些索引可以使用。
哪些索引被实际使用。
表之间的引用。
每张表有多少行被优化器查询。
11)MyISAM 和 InnoDB:
MyISAM:不支持外键,不支持事务,使用表锁,即使操作一条记录也会锁住整个表, 不适合高并发的操作,只缓存索引,不缓存真实数据。
InnoDB:支持外键,支持事务,行锁,操作时只锁某一行,不对其它行有影响, 适合高并发的操作,不仅缓存索引还要缓存真实数据,对内存要求较高,而且内存大小对性能有决定性的影响。
2 者 select count( * ) 哪个更快,为什么?
MyISAM 更快,因为 MyISAM 内部维护了一个计数器,可以直接调取。
12)SQL 语句的执行顺序:
查询中用到的关键词主要包含六个,并且他们的顺序依次为:
select–from–where–group by–having–order by
其中 select 和 from 是必须的,其他关键词是可选的,这六个关键词的执行顺序与
sql 语句的书写顺序并不是一样的,而是按照下面的顺序来执行:
from–where–group by–having–select–order by
13)数据库的三范式是什么?
(1)第一范式:强调的是列的原子性,即数据库表的每一列都是不可分割的原子数据项;
(2)第二范式:要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性;
(3)第三范式:任何非主属性不依赖于其它非主属性。
14)索引按照数据结构来说主要包含B+树和Hash索引。B+树是左小右大的顺序存储结构,非叶子节点只包含id索引列,而叶子节点包含索引列和数据,这种数据和索引在一起存储的索引方式叫做聚簇索引,一张表只能有一个聚簇索引。假设没有定义主键,InnoDB会选择一个唯一的非空索引代替,如果没有的话则会隐式定义一个主键作为聚簇索引。
15)什么是覆盖索引和回表:
覆盖索引指的是在一次查询中,如果一个索引包含或者说覆盖所有需要查询的字段的值,我们就称之为覆盖索引,而不再需要回表查询。而要确定一个查询是否是覆盖索引,我们只需要explain sql语句看Extra的结果是否是“Using index”即可。
16)锁的类型有哪些:
mysql锁分为共享锁和排他锁,也叫做读锁和写锁。
读锁是共享的,可以通过lock in share mode实现,这时候只能读不能写。
写锁是排他的,它会阻塞其他的写锁和读锁。从颗粒度来区分,可以分为表锁和行锁两种。表锁会锁定整张表并且阻塞其他用户对该表的所有读写操作,比如alter修改表结构的时候会锁表。行锁又可以分为乐观锁和悲观锁,悲观锁可以通过for update实现,乐观锁则通过版本号实现。
17)ACID靠什么保证的呢?
A原子性由undo log日志保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sql。
C一致性一般由代码层面来保证。
I隔离性由MVCC来保证。
D持久性由内存+redo log来保证,mysql修改数据同时在内存和redo log记录这次操作,事务提交的时候通过redo log刷盘,宕机的时候可以从redo log恢复。
18)什么是MVCC?
MVCC叫做多版本并发控制,实际上就是保存了数据在某个时间节点的快照。我们每行数实际上隐藏了两列,创建时间版本号,过期(删除)时间版本号,每开始一个新的事务,版本号都会自动递增。MySQL 的可重复读是使用 MVCC 实现的,MVCC 只作用于 RC(Read Committed)和 RR(Repeatable Read)级别。
19)mysql主从同步怎么做:
mysql主从同步的原理:
(1)master提交完事务后,写入binlog 。
(2)slave连接到master,获取binlog。
(3)master创建dump线程,推送binlog到slave。
(4)slave启动一个IO线程读取同步过来的master的binlog,记录到relay log中继日志中。
(5)slave再开启一个sql线程读取relay log事件并在slave执行,完成同步。
(6)slave记录自己的binlog。
由于mysql默认的复制方式是异步的,主库把日志发送给从库后不关心从库是否已经处理,这样会产生一个问题就是假设主库挂了,从库处理失败了,这时候从库升为主库后,日志就丢失了。由此产生两个概念。
全同步复制:
主库写入binlog后强制同步日志到从库,所有的从库都执行完成后才返回给客户端,但是很显然这个方式的话性能会受到严重影响。
半同步复制:
和全同步不同的是,半同步复制的逻辑是这样,从库写入日志成功后返回ACK确认给主库,主库收到至少一个从库的确认就认为写操作完成。
20)为什么Mongodb索引用B树,而Mysql用B+树?
B树的两个明显特点:
树内的每个节点都存储数据。
叶子节点之间无指针相邻。
B+树的两个明显特点:
数据只出现在叶子节点。
所有叶子节点增加了一个链指针。
(1) B树的树内存储数据,因此查询单条数据的时候,B树的查询效率不固定,最好的情况是O(1)。我们可以认为在做单一数据查询的时候,使用B树平均性能更好。但是,由于B树中各节点之间没有指针相邻,因此B树不适合做一些数据遍历操作。
(2) B+树的数据只出现在叶子节点上,因此在查询单条数据的时候,查询速度非常稳定。因此,在做单一数据的查询上,其平均性能并不如B树。但是,B+树的叶子节点上有指针进行相连,因此在做数据遍历的时候,只需要对叶子节点进行遍历即可,这个特性使得B+树非常适合做范围查询。
由于关系型数据库和非关系型数据的设计方式上的不同。Mysql中数据遍历操作比较多,所以用B+树作为索引结构。而Mongodb是做单一查询比较多,数据遍历操作比较少,所以用B树作为索引结构。关系型数据库做较多关联查询,涉及到了join操作,无外乎从一个表中取一个数据,去另一个表中逐行匹配,如果索引结构是B+树,叶子节点上是有指针的,能够极大的提高这种一行一行的匹配速度!
21)为什么MySQL数据库要用B+树存储索引?而不用红黑树、Hash、B树?
红黑树:如果在内存中,红黑树的查找效率比B树更高,但是涉及到磁盘操作,B树就更优了。因为红黑树是二叉树,数据量大时树的层数很高,从树的根结点向下寻找的过程,每读1个节点,都相当于一次IO操作,因此红黑树的I/O操作会比B树多的多。
hash 索引:如果只查询单个值的话,hash 索引的效率非常高。但是 hash 索引有几个问题:1)不支持范围查询;2)不支持索引值的排序操作;3)不支持联合索引的最左匹配规则。
B树索引:B树索相比于B+树,在进行范围查询时,需要做局部的中序遍历,可能要跨层访问,跨层访问代表着要进行额外的磁盘I/O操作;另外,B树的非叶子节点存放了数据记录的地址,会导致存放的节点更少,树的层数变高。
21)谈谈你对聚簇索引的理解?
聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。聚簇索引将索引和数据行放到了一块,找到索引也就找到了数据。因为无需进行回表操作,所以效率很高。InnoDB 中必然会有,且只会有一个聚簇索引。通常是主键,如果没有主键,则优先选择非空的唯一索引,如果唯一索引也没有,则会创建一个隐藏的row_id 作为聚簇索引。至于为啥会只有一个聚簇索引,其实很简单,因为我们的数据只会存储一份。MyisAM引擎没有聚簇索引。索引的存储和数据的存储是分离的,也就是说找到了索引但没找到数据,需要根据索引上的值(主键)再次回表查询,非聚簇索引也叫做辅助索引。
什么是回表查询?InnoDB 中,对于主键索引,只需要走一遍主键索引的查询就能在叶子节点拿到数据。而对于普通索引,叶子节点存储的是 key + 主键值,因此需要再走一次主键索引,通过主键索引找到行记录,这就是所谓的回表查询,先定位主键值,再定位行记录。
走普通索引,一定会出现回表查询吗?
不一定,如果查询语句所要求的字段全部命中了索引,那么就不必再进行回表查询。很容易理解,有一个 user 表,主键为 id,name 为普通索引,则再执行:select id, name from user where name = ‘joonwhee’ 时,通过name 的索引就能拿到 id 和 name了,因此无需再回表去查数据行了。
22)mysql查询性能的优化方法?
1、对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
2、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描。
3、应尽量避免在 where 子句中使用!=或<>操作符,否则引擎将放弃使用索引而进行全表扫描。
4、应尽量避免在 where 子句中使用or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。
5、in和 not in 也要慎用,否则会导致全表扫描。
23)谈谈你对MySQL水平切分和垂直切分的理解?
垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。
通常我们按以下原则进行垂直拆分:
(1)把不常用的字段单独放在一张表;
(2)把text,blob等大字段拆分出来放在附表中;
(3)经常组合查询的列放在一张表中;
垂直拆分更多时候就应该在数据表设计之初就执行的步骤,然后查询的时候用join关键起来即可;
水平拆分是指数据表行的拆分,表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放。
垂直切分的优缺点介绍:
优点:拆分后业务清晰,拆分规则明确。系统之间整合或扩展容易。数据维护简单。
缺点:部分业务表无法join,只能通过接口方式解决,提高了系统复杂度。受每种业务不同的限制存在单库性能瓶颈,不易数据扩展跟性能提高。事务处理复杂。由于垂直切分是按照业务的分类将表分散到不同的库,所以有些业务表会过于庞大,存在单库读写与存储瓶颈,所以就需要水平拆分来做解决。
水平切分的优缺点介绍:
优点:拆分规则抽象好,join操作基本可以数据库做。不存在单库大数据,高并发的性能瓶颈。应用端改造较少。提高了系统的稳定性跟负载能力。
缺点:拆分规则难以抽象。分片事务一致性难以解决。数据多次扩展难度跟维护量极大。跨库join性能较差。垂直切分和水平切分共同的特点和缺点有:引入分布式事务的问题。跨节点Join的问题。跨节点合并排序分页问题。多数据源管理问题。
24)乐观锁和悲观锁:
悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的。
25)MySQL数据库cpu飙升到500%的话他怎么处理?
当 cpu 飙升到 500%时,先用操作系统命令 top 命令观察是不是 mysqld 占用导致的,如果不是,找出占用高的进程,并进行相关处理。
如果是 mysqld 造成的, show processlist,看看里面跑的 session 情况,是不是有消耗资源的 sql 在运行。找出消耗高的 sql,看看执行计划是否准确, index 是否缺失,或者实在是数据量太大造成。
一般来说,肯定要 kill 掉这些线程(同时观察 cpu 使用率是否下降),等进行相应的调整(比如说加索引、改 sql、改内存参数)之后,再重新跑这些 SQL。
也有可能是每个 sql 消耗资源并不多,但是突然之间,有大量的 session 连进来导致 cpu 飙升,这种情况就需要跟应用一起来分析为何连接数会激增,再做出相应的调整,比如说限制连接数等。
26)什么是 Buffer Pool?
Buffer Pool 是 InnoDB 维护的一个缓存区域,用来缓存数据和索引在内存中,主要用来加速数据的读写,如果 Buffer Pool 越大,那么 MySQL 就越像一个内存数据库,默认大小为 128M。
InnoDB 会将那些热点数据和一些 InnoDB 认为即将访问到的数据存在 Buffer Pool 中,以提升数据的读取性能。
InnoDB 在修改数据时,如果数据的页在 Buffer Pool 中,则会直接修改 Buffer Pool,此时我们称这个页为脏页,InnoDB 会以一定的频率将脏页刷新到磁盘,这样可以尽量减少磁盘I/O,提升性能。
27)innoDB 锁的算法有哪几种?
Record lock:记录锁,单条索引记录上加锁,锁住的永远是索引,而非记录本身。
Gap lock:间隙锁,在索引记录之间的间隙中加锁,或者是在某一条索引记录之前或者之后加锁,并不包括该索引记录本身。
Next-key lock:Record lock 和 Gap lock 的结合,即除了锁住记录本身,也锁住索引之间的间隙。