c++后台开发面试常见知识点总结(四)数据库

  • 数据库的索引类型
  • 聚集索引和非聚集索引的区别(叶节点存储内容)
  • 唯一性索引和主码索引的区别
  • 索引的优缺点,什么时候使用索引,什么时候不能使用索引(重点)
  • 索引最左前缀问题
  • 数据库中事务的ACID
  • 数据库隔离性设置不同会出现的问题(脏读、不可重复读、丢失修改、幻读)
  • Mysql有四个隔离级别:未提交读,提交读,可重复读,可串行化。
  • Mysql的优化(高频,索引优化,性能优化)
  • 数据库引擎介绍,innodbmyisam的特点与区别
  • 数据库连接池的作用
  • 讲讲你用过的所有锁,除了互斥锁与读写锁比如自旋锁,递归锁,乐观锁,悲观锁
  • 两段锁协议
  • 关系型和非关系型数据库的区别(各自优点)
  • 数据库的范式
  • Mysql的表空间方式,各自特点。
  • 分布式事务
  • 视图的作用与使用方法(如何删除等)
  • 分库分表,主从复制,读写分离。(我不会,也没碰到过)
  • memcache中的数据结构是如何实现的
  • memcache,redis内部存储数据原理

(1) 数据库的索引类型

索引是在存储引擎层实现的,不同存储引擎具有不同的索引类型和实现。

B+Tree索引 :索引是大多数 MySQL 存储引擎的默认索引类型。如InnoDB 引擎和MyISAM 存储引擎。

哈希索引:InnoDB 引擎有一个特殊的功能叫“自适应哈希索引”,当某个索引值被使用的非常频繁时,会在 B+Tree 索引之上再创建一个哈希索引,这样就让 B+Tree 索引具有哈希索引的一些优点,比如快速的哈希查找。哈希索引能以 O(1) 时间进行查找,但是失去了有序性,它具有以下限制:1.无法用于排序与分组;2.只支持精确查找,无法用于部分查找和范围查找。

全文索引:MyISAM 存储引擎支持全文索引,用于查找文本中的关键词,而不是直接比较是否相等。查找条件使用 MATCH AGAINST,而不是普通的 WHERE。全文索引一般使用倒排索引实现,它记录着关键词到其所在文档的映射。InnoDB 存储引擎在 MySQL 5.6.4 版本中也开始支持全文索引。

空间数据索引(R-Tree)MyISAM 存储引擎支持空间数据索引,可以用于地理数据存储。空间数据索引会从所有维度来索引数据,可以有效地使用任意维度来进行组合查询。

必须使用 GIS 相关的函数来维护数据。

(2) 聚集索引和非聚集索引的区别(叶节点存储内容)

聚集索引:InnoDB主索引是聚簇索引,在索引中保存了数据,数据库的表是通过主索引组织起来的,B+树的叶节点的数据域存储的完整的数据记录。一个表只能有一个聚簇索引。

辅助索引的叶子节点的 data 域记录着主键的值,因此在使用辅助索引进行查找时,需要先查找到主键值,然后再到主索引中进行查找。通常默认以自动递增的值为主索引的主键,而不是以一个唯一的列作为主键。以唯一的列作为主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。

非聚集索引:MyISAM提供的是非聚集索引。MyISAM主索引和辅助索引都是非聚集索引。B+树的叶节点,存储的是指向记录的指针。


(3) 唯一性索引和主码索引的区别

主键约束比唯一索引约束严格,当没有设定主键时,非空唯一索引自动称为主键。对于主键和唯一索引的一些区别主要如下:1.主键不允许空值,唯一索引允许空值。2.主键只允许一个,唯一索引允许多个。 3.主键产生唯一的聚集索引,唯一索引产生唯一的非聚集索引。

在使用InnoDB存储引擎时,如果没有特别的需要,请永远使用一个与业务无关的自增字段作为主键。而不是选择使用如学号或身份证号这种唯一字段作为主键。

创建唯一索引的目的往往不是为了提高访问速度,而只是为了避免数据出现重复。

(4)索引的优缺点,什么时候使用索引,什么时候不能使用索引(重点)

索引虽然加快了查询速度,但索引也是有代价的:索引文件本身要消耗存储空间,同时索引会加重插入、删除和修改记录时的负担,另外,MySQL在运行时也要消耗资源维护索引,因此索引并不是越多越好。一般两种情况下不建议建索引。

第一种情况是表记录比较少,没必要建索引,让查询做全表扫描就好了。通常记录数不超过 2000可以考虑不建索引,超过2000条可以酌情考虑索引。

另一种不建议建索引的情况是索引的选择性较低。(索引的选择性)


(5) 索引最左前缀问题

当按照索引中所有列进行精确匹配(这里精确匹配指“=”或“IN”匹配)时,索引可以被用到。

当查询条件精确匹配索引的左边连续一个或几个列时,只能用到一部分索引,即条件所组成的最左前缀。


(6)数据库中事务的ACID(四大特性都要能够举例说明,理解透彻,比如原子性和一致性的关联,隔离性不好会出现的问题)

原子性:事务被视为不可分割的最小单元,事务的所有操作要么全部提交成功,要么全部失败回滚。回滚可以用日志来实现,日志记录着事务所执行的修改操作,在回滚时反向执行这些修改操作即可。

一致性:数据库在事务执行前后都保持一致性状态。在一致性状态下,所有事务对一个数据的读取结果都是相同的。

隔离性:一个事务所做的修改在最终提交以前,对其它事务是不可见的。

持久性:一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。可以通过数据库备份和恢复来实现,在系统发生奔溃时,使用备份的数据库进行数据恢复。

事务的 ACID 特性之间不是一种一种平级关系:

  • 只有满足一致性,事务的执行结果才是正确的。
  • 在无并发的情况下,事务串行执行,隔离性一定能够满足。此时要只要能满足原子性,就一定能满足一致性。
  • 在并发的情况下,多个事务并发执行,事务不仅要满足原子性,还需要满足隔离性,才能满足一致性。
  • 事务满足持久化是为了能应对数据库奔溃的情况。

MySQL 默认采用自动提交模式。也就是说,如果不显式使用START TRANSACTION语句来开始一个事务,那么每个查询都会被当做一个事务自动提交。

在并发的情况下,事务的隔离性不能实现时,就会出现脏读,不可重复读,丢失修改,幻影读等问题。

 

(7) 数据库隔离性设置不同会出现的问题(脏读、不可重复读、丢失修改、幻读)

丢失修改:T1 和 T2 两个事务都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改。则T1丢失修改。可在T1修改时对数据加上X锁,直到T1结束锁释放,在此期间T2不可修改该数据。

脏读:事务T1在修改数据a后,未commit。事务T2读取数据a,随后T1 rollback

撤销修改,则T2读到的数据a为脏数据。提交读隔离级别解决脏读问题。

不可重复读:同一个事务中多次读取同样数据的结果不一样。T2 读取一个数据,T1 对该数据做了修改。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同。可在T2读取数据时对数据加上S锁,直到T2结束锁释放,在此期间T1不可修改该数据。可重复读隔离级别解决了不可重复读的问题。 

幻读:T1 读取某个范围的数据,T2 在这个范围内插入新的数据,T1 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。同上,同样可以加S锁解决该问题。

 MySQL 的 InnoDB 存储引擎,在可重复读(REPEATABLE READ)隔离级别下,使用 MVCC + Next-Key Locks 可以解决幻读问题。


(8) 数据库的隔离级别,mysql和Oracle的隔离级别分别是什么

Mysql有四个隔离级别:未提交读,提交读,可重复读,可串行化。

未提交读:事务中的修改,即使没有提交,对其它事务也是可见的。总是读取最新的数据行即是未提交读隔离级别。

提交读:一个事务只能读取已经提交的事务所做的修改。换句话说,一个事务所做的修改在提交之前对其它事务是不可见的。

可重复读:保证在同一个事务中多次读取同样数据的结果是一样的。MVCC(多版本并发控制)实现提交读和可重复读这两种隔离级别。

 

可串行化:强制事务串行执行。遵循两段锁协议实现可串行化。

(9) Mysql的优化(高频,索引优化,性能优化)

查询优化:写SQL语句时,可以先select再JOIN,尽量把一元操作(select)往树叶上压,从而减小二元操作的规模。

 

索引优化:在进行查询时,索引列不能是表达式的一部分,也不能是函数的参数,否则无法使用索引。

在需要使用多个列作为条件进行查询时,使用多列索引比使用多个单列索引性能更好。

让选择性最强的索引列放在前面,索引的选择性是指:不重复的索引值和记录总数的比值。最大值为 1,此时每个记录都有唯一的索引与其对应。选择性越高,查询效率也越高。

对于 类似VARCHAR 类型的列,必须使用前缀索引,只索引开始的部分字符。对于前缀长度的选取需要根据索引选择性来确定。


(10) 数据库引擎介绍,innodb和myisam的特点与区别。

Innodb:InnoDB 是 MySQL 默认的事务型存储引擎,只有在需要 InnoDB 不支持的特性时,才考虑使用其它存储引擎。实现了四个标准的隔离级别,默认级别是可重复读。在可重复读隔离级别下,通过多版本并发控制(MVCC)+ 间隙锁(next-key locking)防止幻影读。主索引是聚簇索引,在索引中保存了数据,从而避免直接读取磁盘,因此对查询性能有很大的提升。内部做了很多优化,包括从磁盘读取数据时采用的可预测性读、能够加快读操作并且自动创建的自适应哈希索引、能够加速插入操作的插入缓冲区等。

Myisam:MyISAM 提供了大量的特性,包括压缩表、空间数据索引等。不支持事务。不支持行级锁,只能对整张表加锁,读取时会对需要读到的所有表加共享锁,写入时则对表加排它锁。但在表有读取操作的同时,也可以往表中插入新的记录,这被称为并发插入。

比较

事务:InnoDB 是事务型的,可以使用 Commit 和 Rollback 语句。

并发:MyISAM 只支持表级锁,而 InnoDB 还支持行级锁。

外键:InnoDB 支持外键。

崩溃恢复:MyISAM 崩溃后发生损坏的概率比 InnoDB 高很多,而且恢复的速度也更慢。

备份:InnoDB 支持在线热备份。

其它特性:MyISAM 支持压缩表和空间数据索引。

 

11数据库连接池的作用

什么是数据库连接池:创建数据库连接是一个很耗时的操作,也容易对数据库造成安全隐患。所以,在程序初始化的时候,集中创建多个数据库连接,并把他们集中管理,供程序使用,可以保证较快的数据库读写速度,还更加安全可靠。数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。连接池必须要确保某一时间内一个 conn 只能分配给一个线程。不同 conn 的事务是相互独立的。

 

Java应用程序以传统的连接机制访问数据库的过程:①装载数据库驱动程序;②通过JDBC建立数据库连接;③访问数据库,执行SQL语句;④断开数据库连接。

使用了数据库连接池的机制:①程序初始化时创建连接池。②使用时向连接池申请可用连接③使用完毕,将连接返还给连接池。④程序退出时,断开所有连接,并释放资源。

 

(12)讲讲你用过的所有锁,除了互斥锁与读写锁比如自旋锁,递归锁,乐观锁,悲观锁

1.共享锁(又称读锁)、排它锁(又称写锁):

InnoDB引擎的锁机制:InnoDB支持事务,支持行锁和表锁用的比较多,Myisam不支持事务,只支持表锁。

 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。

排他锁(X):允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的共享读锁和排他写锁。

意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。

意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。

2.乐观锁、悲观锁:

悲观锁:悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)

乐观锁:

乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做(一般是回滚事务)。那么我们如何实现乐观锁呢,一般来说有以下2种方式:

 (13)两段锁协议

加锁和解锁分为两个阶段进行。事务遵循两段锁协议是保证可串行化调度的充分条件。

(充分非必要,遵循一定保证可串行化,不遵循也可能会串行化)可串行化调度是指,通过并发控制,使得并发执行的事务结果与某个串行执行的事务结果相同。

(14) 关系型和非关系型数据库的区别(各自优点)

 (15)数据库的范式

不符合范式的关系(表),会产生很多异常,范式理论是为了解决异常。常见的异常有冗余数据,修改异常,删除异常,插入异常。高级别范式的依赖于低级别的范式,1NF 是最低级别的范式。

1NF:属性不可分。不满足1NF不是一个合法的关系表。

2NF:每个非主属性完全函数依赖于键码。不满足2NF可能会出现上述4种异常。可以通过分解表来满足。

3NF:非主属性不传递函数依赖于键码。不满足3NF可能会出现上述4种异常。可以通过分解表来满足。

 

两段锁协议

加锁和解锁分为两个阶段进行。事务遵循两段锁协议是保证可串行化调度的充分条件。

(充分非必要,遵循一定保证可串行化,不遵循也可能会串行化)

 

可串行化调度是指,通过并发控制,使得并发执行的事务结果与某个串行执行的事务结果相同。


 Mysql的表空间方式,各自特点。

innodb引擎使Mysql有共享表空间和独占表空间两种数据存储方式。

 

共享表空间: 一个数据库的所有的表数据,索引数据共享一个表空间。多个表及索引在表空间中混合存储。

优点:可以把表空间分成多个文件存放到各个磁盘上,一个表可以分布在不同步的文件上。

表空间可以分成多个文件存放到各个磁盘,所以表也就可以分成多个文件存放在磁盘上,表的大小不受文件,磁盘大小的限制。数据和文件放在一起方便管理。

缺点:多个表及索引在表空间中混合存储,当一个表做了大量删除操作后表空间中将会有大量的空隙。共享表空间大小不会收缩。

 

独立表空间:每个表都有自已独立的表空间。每个表的数据和索引都会存在自已的表空间中。

其它信息如,回滚(undo)信息、仍放在默认表空间。默认表空间不会收缩空间。

优点:可以实现单表在不同的数据库中移动。 对于使用独立表空间的表,不管怎么删除,表空间的碎片不会太严重的影响性能,而且还有机会处理。独立表空间大小可以收缩。

缺点:单表增加过大,如超过100个G。

总结:相比较之下,使用独占表空间的效率以及性能会更高一点。共享表空间以及独占表空间之间的转化可以通过在配置文件中设置innodb_file_per_table参数实现。为OFF说明所使用的是独占表空间。


(18) 分布式事务

一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

(21) 视图的作用与使用方法(如何删除等)

视图是虚拟的表,对视图的操作和对普通表的操作一样。但视图本身不包含数据,也就不能对其进行索引操作。视图具有如下好处:1.通过只给用户访问视图的权限,保证数据的安全性;2.简化复杂的 SQL 操作,比如复杂的连接;3. 更改数据格式和表示;4. 只使用实际表的一部分数据;

CREATE VIEW myview AS

SELECT Concat(col1, col2) AS concat_col, col3*col4 AS compute_col

FROM mytable

WHERE col5 = val;

总结:视图包含的不是表的数据,是对select查询的封装。可以简化数据处理,重新格式化基础数据。

(22) 分库分表,主从复制,读写分离。(我不会,也没碰到过)

分库分表:

水平切分:又称为 Sharding,它是将同一个表中的记录拆分到多个结构相同的表中。当一个表的数据不断增多时,Sharding 是必然的选择,它可以将数据分布到集群的不同节点上,从而缓存单个数据库的压力。事务:使用分布式事务来解决事务问题。JOIN:可以将原来的 JOIN 查询分解成多个单表查询,然后在用户程序中进行 JOIN。

 

memcache中的数据结构是如何实现的

memcache是分布式缓存服务器,通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。memcache中保存的数据都存储在memcache内置的内存存储空间中。重启memcache、操作系统都会导致全部数据消失。当memcache内容容量达到指定值之后,memcache就基于LRU算法淘汰淘汰缓存。memcache本身是为缓存而设计的服务器,因此没有过多考虑数据永久性的问题。

memcache,redis内部存储数据原理

https://blog.csdn.net/session_time/article/details/52618215

redis与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。


(23) 项目中哪里用到了数据库,怎么用的

你可能感兴趣的:(c++后台开发面试常见知识点总结(四)数据库)