数据库

1、数据库的范式
数据库第一范式:数据表中的每一个字段都是不可再拆分的原子值。
举例,淘宝地址
数据库第二范式,数据表中的每一列都和主键相关,而不能只和主键的一部分相关。
也就是说数据表中只能存放一种数据。
举例:订单信息表中,把订单编号和商品编号放在一起作为联合主键。
所以要把订单信息表拆分,把订单项目和商品编号额外放在一个表中。
第三范式:保证每一列都和主键直接相关而不是间接相关。
也就是说第二范式下,每一列多和主键相关,但除此之外还可能和其他列相关。第三范式则去除了这一影响。

2、数据库的引擎
Myisam和innodb和Memory
Myisam是默认的MYsql插件式存储引擎,在web,数据仓储等环境下常用的存储引擎之一。
Innodb用于事务处理应用程序,具有众多特性,包括ACID事务支持。原子性,一致性,隔离性,持久性。
原子性:事务是最小的执行单位,不可分割。要么不完成,要么完成。

一致性:执行事务前后,数据保持一致,多个事务对同一个数据读取结果相同。拿转账来说。

隔离性:并发访问数据库时,一个用户的事务,不给其他事务所干扰。并发事务之间数据库库是独立的。

持久性:一个事务被提交后,他对数据库中的数据改变是持久的,即使数据库发生故障,也没有变化。

MEMORY将所有数据保存在内存中,在需要快速查找引用和其他类似数据环境下,可提供极快的访问。

3、什么是索引
索引就是数据表中某一列或多列的值排序后的存储结构。

3、聚集索引和非聚集索引
聚集索引就是索引列按照一定的严格的规则排列的。而表中数据的物理顺序与键值(索引)顺序相同。一个表都能有一个聚集索引。聚集索引有更快的检索速度。叶子结点存储了真实的数据。

非聚集索引的逻辑顺序与磁盘上的物理存储顺序不同,页层不包含数据页,页结点包含索引字段及指向数据也数据行的逻辑指针。所以非聚集索引不能直接获取数据。
该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同。

MYISAM用的是非聚集索引,即数据和索引落在不同的文件上,MYISAM在建表时以主键作为KEY来建立主索引B+树,树的叶子节点存的是对应数据的物理地址。

INNODB是聚集索引方式,因此数据和索引都存储在同一个文件里。首先INNODB会根据主键ID作为KEY建立索引B+树。

如果利用表里其他字段加索引建立索引树。innoDB会建立这个新字段的索引B+树,节点里存的是user_name这个key,叶子结点存储的是主键KEY。拿到主键KEY后,INNODB才会去主键索引树立根据对应的主键key查到对应的数据。

为什么其他索引树不存储数据,为了节省空间。

聚集索引和非聚集索引的区别:
1、聚集索引一个表只能有一个,而非聚集索引一个表可以存在多个
2、聚集索引存储记录在物理上是连续存在的,而非聚集索引是逻辑上连续
3、聚集索引,物理存储索引按索引排序,索引的键值顺序决定了表数据行的物理存储顺序,

非聚集索引:物理存储不按照索引排序,非聚集索引则是普通索引,仅仅只是对数据创建对应的索引,不影响整个表的物理存储顺序。
索引是通过多叉树的数据结果来描述的,聚集索引的叶结点就是数据结点,而非聚集索引的叶结点仍然是索引结点。只不过有一个指针指向对应的数据块。

聚集索引插入数据时速度要慢,查询数据比非聚集索引要快。

3、最左匹配原则
所谓最左优先,就是以最左边为起点的任何连续的索引都能匹配上,但同时遇到范围查询(>,<,between,like)就会停止匹配。最后一个范围也会匹配,但是范围查询之后不会匹配。

4、联合索引就是两个列或两个列以上的索引称为联合索引。

5、覆盖索引

就是select的数据列只用从索引中就能取得,不必从数据表中回表查询。

覆盖索引适用的场景类型:
1、覆盖索引并不适用于任意的索引类型,索引必须存储列的值。
2、hash和full—text索引不存储值
3、不同的存储引擎实现覆盖索引是不同的
4、并不是所有的存储引擎都支持他们
5、如果要使用覆盖索引,一定要注意select列表值中取出需要的列。

3、innodb的特性
a.插入缓冲

b.二次写

c.自适应哈希
innoDB会监控表上索引页的查询,如果观察到建立哈希索引可以带来速度提升,则自动建立索引。

d.预读

innoDB特点:
1、innoDB支持事务,支持事务的四个隔离级别,支持多版本读。
2、行级锁定,通过索引实现。全表扫描仍然是表锁。
3、读写阻塞与事务隔离级别相关。
4、具有非常高效的缓存特性,能缓存索引和数据。
5.支持分区和表空间,类似oracle数据库。
6、支持外键约束。
7、所有Secondary Index都会保存主键信息。
8.整个表和主键以Cluster方式存储,形成一个平衡树。

innodb调优

1、主键尽可能小,避免给Secondary index 带来过大的空间负担。
2、建立有效索引避免全表扫描,因为会使用表锁。
3、尽可能缓存所有的索引和数据,提高响应速度,减少产品IO消耗。
4、在大批量小插入的时候,尽量自己控制事务而不要使用autocommit自动提交。有开关可以控制提交方式
5、合理设置innodb_flush_log_at_trx_commit参数值,不要过度追求安全性。
如果innodb_flush_log_at_trx_commit的值为0,log buffer每秒就会被刷写日志文件到磁盘,提交事务的时候不做任何操作。
6、避免主键更新,因为这会带来大量的数据移动。

对硬件要求高

4、事务的隔离级别

脏读:当一个事务正在访问数据库并且对数据进行修改,这种修改还没有提交到数据中,这时另一个事务也访问了数据,然后使用了数据。因为这个数据还没有提交,所以这个数据是脏数据,脏数据所做的操作可能是不正确的。

不可重复读:是指在一个事务内多次读同一个数据,在这个事务还没有结束时,另一个事务也访问数据。那么在第一个事务中的两个读数据之间,由于第二个事务的修改导致第一个事务二次读取的数据可能不太一样,这样就发生了一个事务内二次读取的数据不一样。

幻读(Phantom read): 幻读与不可重复度类似,他发生了在一个事务T1读取了几行数据后,接着另一个并发事务T2插入了一些数据,在随后的查询中,第一个事务T1会出现多了一些原本不存在的记录,就好像发生了幻觉一样。

不可重复读的重点是修改,幻读的重点在于新增或者删除。

事务的隔离几倍分为四种:
由低到高分别为
Read uncommitted(读取未提交):最低的隔离级别,允许读取尚未提交的数据变更,可能导致脏读,幻读或不可重复读。
Read-COMMITTED(读取已提交):允许读取并发事务已经提交的数据,可以组织脏读,但是幻读或不可重复读仍有可能发生。
REPEATTABLE-READ:(可重复读)对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改IDE,可以组织脏读和不可重复度读,但幻读仍然有可能发生。
SERIALIZABLE(可串行化):最高的隔离级别,完全服从ACID的隔离级别,所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是该级别可以组织脏读,不可重复读,幻读。

MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)

4、b+是怎么保证平衡的

6、事务并发的三大问题、事务隔离级别及实现原理
3、锁:悲观锁、乐观锁
悲观锁就是要对数据库中一条数据进行修改时,对该数据进行加锁,防止并发,需要借助数据库锁机制,在修改数据前锁定。
悲观锁具有强烈的独占和排他特性,他指的是对数据被外界修改持保守态度。因为在整个数据处理过程中,数据处于锁定状态,悲观锁的实现往往依靠数据库提供的锁机制。
悲观的意思是,修改的时候默认其他进程可能会访问修改数据。传统的关系型数据库的表锁,行锁,读锁,写锁都是如此。
悲观锁降低了并发性,增加了开销。
悲观锁分为共享锁(读锁)和排他锁(写锁);共享锁多个事务能同时对同一数据读,但不能写。
排他锁,不能与其他锁并存,如果一个事务获取了数据的排他锁,其他事务就不能再获取数据的其他锁。

乐观锁就是假设最好的情况,每次拿数据都认为事务不会修改数据,所以不会上锁,但是在更新的时候回判断一下这期间,别人有没有更新这个数据,可以通过版本号合CAS算法来实现。
乐观锁不会依靠数据本身的锁,而是依靠数据本身来保证数据的正确性。
版本号机制,在提交更新的时候,会查看自己的版本号和当前版本号是否一致,如果一致才更新。如果不一致则重新获取。

CAS算法,包含一个内存位置V,一个预期原值,一个要更新的值,只有当预期原值和内存位置的值相同时,才会通过原子操作更新。

多读用乐观锁,多写用悲观锁。

CAS问题:
1、ABA问题
2、循环等待占用CPU资源
3、只能保证一个共享变量的原子操作

索引的类型有几种?
FULLTEXT,HASH,BTREE,RTREE.
FULLTEXT索引

也就是全文索引,目前只有MyISAM引擎支持。目前只有 CHAR、ARCHAR ,TEXT 列上可以创建全文索引。数据量的时候,先放数据在,再创建索引会比先建索引再放数据快一点。

哈希索引
哈希索引就是在一列或几列通过哈希函数得到一个哈希值,一个key值允许对应一个value;
哈希索引的特点,哈希索引仅仅能满足"=",“IN"和”<=>“查询,不能使用范围查询。
1、Hash 索引仅仅能满足”=",“IN"和”<=>"查询,不能使用范围查询。

2、hash索引无法用来排序,因为hash函数计算后的哈希值的大小关系和原来的key值没有关系。
Hash 索引无法被用来避免数据的排序操作。

3、对于组合索引,hash索引是在计算hash值时是把所有的组合索引键合并后再一起计算哈希值,而不是单独计算hash值。

4、hash索引遇到大量hash值相等的情况后性能并不一定会被B-TREE索引高。

为什么采用主键自增索引?
如果在中间插入的话,会产生页分裂,移动元素,而如果是自增的话,每次新插入的都会比前面大,所以直接在后面插入就好了

BTREE按照B树对索引列进行排序。

RTREE索引,是空间索引,会从所有维度对数据进行索引。

8、哈希索引和聚簇索引有什么区别?
哈希索引是对索引值取散列函数得到哈希值,所以无法模糊搜索
如果是联合索引,哈希得到的是所有索引列值的哈希值,所以无法联合索引。
索引列经过哈希函数后大小关系和原来的不一样,所以无法应用范围搜索。
如果有多个相同的哈希值,采用拉链法连接的话效率会很低。

联合索引有什么规则?

9.主从复制
主从复制是用来建立一个和主数据库完全一样的数据库环境,称为从数据库。
假设主数据库的数据发生了实时变化,在数据库执行后,会写入本地的日志系统A。如果实时将日志库中的数据库操作事件发给从数据库,从数据收到会写入本地日志系统B,然后一条条将数据库事件在数据库中完成。
影响
影响MySQL-A数据库的操作,在数据库执行后,都会写入本地的日志系统A中。

主从复制,先写日志后写数据。

主从数据库的优点:
1、可以分担主服务器压力,主库写,从库读
2.在从服务器备份,避免在备份的时候影响服务
3、当主服务器出现问题,可以切换到从服务器

主从复制的方式:
同步复制
同步复制就是master的变化必须等待所有从服务器完成才能返回。
异步复制
主服务器只要自己完成自己的数据库操作即可。至于从服务器则不用管理。
半同步复制
master只保证一个从服务器操作成功就返回。

半同步复制
master只保证slaves中的一个操作成功,就返回,其他slave不管。
这个功能,是由google为MYSQL引入的。

10.如何实现日志回滚?binlog了解吗?
保存事务发生之前的数据的一个版本。
binlog是记录所有数据库库表结构变更(CREATE,ALTER)以及表数据修改(INSERT、UPDATE、DELETE)的二进制文件。

binlog不会记录SELECT和SHOW这类操作,因为这类操作对数据本身没有修改,但是可以通过查看通用日志来查看MYSQL执行过的所有语句。

二进制日志包括两类文件:二进制日志索引文件用于记录所有的二进制文件,二进制日志文件用于记录数据库中DDL和DML(除了数据查询语句)语句事件。
DDL(data definition language)数据定义语言
DML(data manipulation language) 数据操纵语言

binlog是事件而不是事务,所以myisam和innodb都有。

11.索引结构,为什么用b+树不用b树

12、MySQL慢查询怎么解决
原因有三:
1、后台数据库中的数据过多,没做数据优化导致后台查询数据很慢
2、前端数据请求-解析-展示过程处理不当
3、网络问题所致

11、数据库查询发生死锁怎么办?

一致性hash

13.mysql的慢查询,如何定位时间?

使用慢查询一般分为四步:
开启慢查询日志(默认是关闭的)
设置慢查询阈值,
确定慢查询日志路径,
确定慢查询日志

数据库的主键索引和非主键索引的区别?
主键只有一个,非主键可以有多个,主键索引是聚集索引,非主键索引是非聚集索引。主键索引的叶子结点是data值,而非主键索引的叶子结点是主键值。

MySQL索引实现方式,树的节点之间的关系,如何进行范围查找

非主键索引的话,索引的叶子结点存储的主键?
为了一致性和节省存储空间考虑,都通过主键索引来找到最终的数据,避免维护多分数据导致不一致的情况。

多个索引在B+树中如何存储
存储的是结构体,包括索引键值列和索引指针。

MySQL事务是如何实现的
原子性、隔离性和持久性都是为了保证一致性
原子性是通过undo_log来实现,将数据所有的增删改写入
持久性是通过redo log来实现,innodb会先写到redo log,然后等到合适的时机再写到内存中

隔离性是通过避免第一类丢失更新和第二类丢失更新来实现。
第一类丢失更新是一个事务撤销的时候,覆盖另一个事务已提交的数据。
第二类丢失更新是一个事务提交的时候,覆盖另一个事务已提交的数据。
而实际上在REPEATEDABLE_READ的隔离级别下,可以通过MVCC解决select幻读。

10、如果没有隔离级别会发生什么?
第一类丢失更新,脏读,不可重复读,幻读,第二类丢失更新
第一类丢失更新
第一类丢失更新是指:一个事务在撤销的时候,覆盖了另一个事务已提交的更新数据

11、MySQL容灾备份

12、多版本并发控制实现机制(MCVV)原理
MVCC是一种并发控制方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务。MVCC在MYSQL INNODB的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写状态,做到即使有读写冲突,也能不加锁非阻塞读。

当前读和快照读
像select lock in share mode,select for update,insert,delete这些操作都是一种当前读,就是它读取的是记录的最新版本,读取时要保证其他并发事务不能修改当前记录,会对读取的记录加锁。

快照读
不加锁得 select就是快照读,及不加锁的非阻塞读,快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读,之所以会出现快照读,是基于提高并发性能的考虑。
快照读的实现时基于多版本并发控制即MVCC,可以认为MVCC是行锁的一个变种,但它在很多情况下避免了加锁操作,降低了快消。基于多版本,所以快照读读的可能不是数据的最新版本呢,有可能是之前的历史版本。
换句话说也就是MVCC是为了实现读写冲突不加锁,而这个读是快照读,而非当前读,当前读实际上是一种加锁的操作,悲观锁。

MVCC多版本并发控制指的是维持一个数据的多版本,使得读写操作没有冲突的概念。
而在MYSQL中,实这么一个MVCC概念,需要具体功能。快照读就是MVCC模型中的非阻塞读。MVCC在MYSQL中的具体实现时由三个隐式字段,undo日志,READ VIEW等完成。

数据库隐式字段,包括
最近修改事务ID:DB_TRX_ID,创建这条记录/最后一次修改该记录事务的ID
回滚指针,DB_ROLL_PTR;指向这条记录的上一个版本
隐藏自增ID:DB_ROW_ID;隐藏主键,如果数据表没有主键,INNODB就会自动以DB_ROW_ID产生一个聚集索引。
实际上还有一个删除flag隐藏字段,也就是说记录被更新或删除并不代表真的被删除,只是删除flag变了。

undo log主要分为两种:
insert undo log
代表事务在insert新记录时产生的undo log,旨在事务回滚时需要,兵器在事务提交后立即丢弃。

update undo log
事务在进行update或delete时产生的undo log,不仅在事务回滚时需要,在快照读时也需要,所以不能随便删除,只有在快照读或事务回滚不涉及该日志时,对应的日志才会被purge线程统一删除。

修改的过程
1、事务修改数据时,数据库会先对该行加排它锁
2、然后把该行数据拷贝到undo log中,作为旧记录,也就是在undo log中有当前行的拷贝副本。最新的旧记录要排在之前的旧记录的前面。
拷贝完成后,修改该行的数据,并修改隐藏字段的事务id为当前事务ID+1,回滚指针指向undo log副本记录。表示上个版本就是它
3、释放锁

READ VIEW
READ VIEW就是对事务快照读操作时产生的读视图。在事务执行快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的ID。

READ VIE遵循可见性算法,主要是将要修改的数据的最新记录中的DB_TRX_ID取出来,与系统当前其他活跃事务的ID去对比,如果DB_TRX_ID跟READ VIEW属性做了某些比较,不符合可见性,会通过DB_ROLL_PTR回滚指针去去除UNDO LOG中的DB_TRX_ID继续比较,遍历链表的DB_TRX_ID,知道找到满足特定条件的DB_TRX_ID.
READ_VIEW包含三个属性,
trx_list,包含当前活跃事务列表
up_limit_id,记录trx_list中的事务最小ID
low_limit_id记录trx_list中的事务最大ID
将当前事务ID取出来去比较,如果小于up_limit_id说明可见,如果大于low_limit_id不可见,如果在之间,则看是否在列表中存在,如果存在说明还未提交,不可见,如果没再说明已提交可以用。

28、在Repeatable Read隔离级别是怎么解决幻读的呢?
通过间隙锁来解决。INNODB支持行锁,行锁是锁住索引。而间隙锁用来锁定索引记录间隙,确保索引记录的间隙不变。间隙锁是针对事务隔离级别REPEATABLE READ以上级别,间隙锁和行锁一起组成了NEXT-KEY LOCK。当INNODB扫描索引记录的时候,会首先对索引记录加上行锁,再对索引记录两边的间隙加上间隙锁。加上间隙锁之后,其他事务就不能在这个间隙插入记录,这样就有效防止了幻读的发生。

是通过间隙锁(Gap Lock)来解决的。我们都知道InnoDB支持行锁,并且行锁是锁住索引。而间隙锁用来锁定索引记录间隙,确保索引记录的间隙不变。间隙锁是针对事务隔离级别为Repeatable Read或以上级别而已的,间隙锁和行锁一起组成了Next-Key Lock。当InnoDB扫描索引记录的时候,会首先对索引记录加上行锁,再对索引记录两边的间隙加上间隙锁(Gap Lock)。加上间隙锁之后,其他事务就不能在这个间隙插入记录。这样就有效的防止了幻读的发生。

29、缓存了解么?写缓存和读缓存可能出现的问题?缓存穿透、雪崩、击穿
穿透就是没有,雪崩就是缓冲全没,击穿就是一个key突然没了

缓存穿透就是查询一个不存在的数据,这个不存在的数据每次请求到存储层查询,就失去了缓存的意义,流量大的时候DB就挂掉了。
解决缓存穿透的方法,采用布隆过滤器,如果不存在的数据会被bitmap拦截。
或者如果查询数据为空,把这个空结果缓冲,不超过5分钟。

缓存雪崩
缓存雪崩就是在我们设置缓存时采用相同的过期时间,导致缓冲在同一时刻失效,请求全部转发到DB,DB瞬时压力过重雪崩。

解决方案
采用加锁或队列方式,保证缓存的单线程写,从而避免失效是大量的并发请求落在底层存储。
在原来的失效时间上增加一个随机值。

缓存击穿
如果过期时间的key在某些时间点被超高发的访问,会变成热点数据。和雪崩的却别在于击穿是一个key。
解决方案
采用互斥锁。

14、一致性哈希算法
在redis集群添加服务器或者宕机的时候,可以使收影响的服务器数量较小

具体做法:
首先求服务器结点的哈希值,然后对2^32-1取模。将服务器配置到一个圆环上。
然后采用同样得 方法求存储数据见的哈希值,并映射到相同的圆上。
然后从数据映射位置开始顺时针查找,将数据保存 到找到的第一个服务器上,如果知道到2^32还是找不到服务器,就会保存到第一台上。

这样的话,如果有一台服务器宕机了,那么受影响的只有这台服务器和逆时针方向上第一台服务器之间的数据受到影响。而如果是增加一台服务器,那么受影响的也只有这个范围内的数据。

如果服务结点太少,则可能有大量数据集中到少量服务器上,这种情况可以增加虚拟结点,也就是一台服务器增加多个哈希值,然后哈希环上放多个结点来解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值