【校招面经】数据库 part2

七、数据库范式

1. 1NF:不存在可以分的属性

2. 2NF:每一个非主属性依赖于关系模型的某个候选键

3. 3NF:不存在非主属性的传递依赖于关系模型的侯选建

4. BCNF:每个属性都不存在传递依赖于关系模型的侯选建

1NF: 字段是最小的的单元不可再分

2NF:满足1NF,表中的字段必须完全依赖于全部主键而非部分主键 (一般我们都会做到)

3NF:满足2NF,非主键外的所有字段必须互不依赖

4NF:满足3NF,消除表中的多值依赖

八、数据库隔离级别

来源:https://blog.csdn.net/sayoko06/article/details/79168895

现在来看看MySQL数据库为我们提供的四种隔离级别:

  ① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。

  ② Repeatable read (可重复读):可避免脏读、不可重复读的发生。事务A读取与搜索条件相匹配的若干行。事务B以插入或删除行等方式来修改事务A的结果集,然后再提交。事务A再读取时,却发现数据发生了变化。造成了幻读。(MySQL默认的隔离级别)

  ③ Read committed (读已提交):可避免脏读的发生。在事务完成提交之前,其他事务看不到该事务的修改结果。执行两次同样的查询可能看到不一样的结果。可重复读,在一条记录上的操作是,不能读取已由其它事务修改了但是未提交的行,其它任何事务也不能修改在当前事务完成之前由当前事务读取的数据。但是对于其它事务插入的新行数据,当前事务第二次访问表行时会检索这一新行。因此,这一个隔离级别的设置解决了 Non-Repeatable Reads 不可重复读取的问题,但是避免不了 Phantom Reads 幻读。

例如:事务T1在读取R1和修改R2,此时T2不能够读取R2也不能修改R1,这样T2的操作就不会影响到T1的操作,但是,如果T1中含有一个统计某个范围内记录数量的操作,而T2在此时正好在此范围内插入了一条记录,则会草成T1的幻读,即第一次读此范围内一共2条数据,而在次读的时候却有了3条数据。

  ④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。

一般的关系型数据库的默认级别就是读已提交,该隔离级别避免了脏读。

九、数据库三层模式两层映射

1.概念模式(Conceptual Schema)

  概念模式是数据库系统中全局数据逻辑结构的描述,是全体用户(应用)公共数据视图,此种描述是一种抽象的描述,它不涉及具体的硬件环境与平台,也与具体的软件环境无关。

  概念模式主要描述数据的概念记录类型及数据以及它们间的关系,它还包括一些数据间的语义约束,对它的描述可用DBMS中的DDL语言定义。

2.外模式(External Schema)

  外模式也称子模式(Subschema)或称用户模式(User’s schema)它是用户的数据视图,亦即是用户所见到的模式的一个部分,它由概念模式推导而出,概念模式给出了系统全局的数据描述而外模式则给出每个用户的局部描述。一个概念模式可以有若干个外模式,每个用户只关心与它有关的模式,这样可以屏蔽大量无关信息且有利于数据保护,因此对用户极为有利。在一般的DBMS中都提供有相关的外模式描述语言(外模式DDL)。

3.内模式(Internal Schema)

  内模式又称物理模式(Physical Schema),它给出了数据库物理存储结构与物理存取方法,如数据存储的文件结构、索引、集簇及hash等存取方式与存取路径,内模式的物理性主要体现在操作系统及文件级上,它还不深入到设备级上(如磁盘及磁盘操作),但近年来有向设备级发展的趋势(如原始磁盘、磁盘分块技术等),DBMS一般提供相关的内模式描述语言(内模式DDL)。

数据模式给出了数据库的数据框架结构,而数据库中的数据才是真正的实体,但这些数据必须按框架所描述的结构组织,以概念模式为框架所组成的数据库叫概念数据库(Conceptual Database),以外模式为框架所组成的数据库叫用户数据库(user’s Database),以内模式为框架所组成的数据库叫物理数据库(Physical Database),这三种数据库中只有物理数据库是真实存在于计算机外存中,其它两种数据库并不真正存在于计算机中,而是通过两种映射由物理数据库映射而成。

  模式的三个级别层次反映了模式的三个不同环境以及它们的不同要求,其中内模式处于最低层,它反映了数据在计算机物理结构中的实际存储形式,概念模式处于中层,它反映了设计者的数据全局逻辑要求,而外模式处于最外层,它反映了用户对数据的要求。

  数据库系统的三级模式是对数据的三个级别抽象,它把数据的具体物理实现留给物理模式,使用户与全局设计者能不必关心数据库的具体实现与物理背景,同时,它通过两级映射建立三级模式间的联系与转换,使得概念模式与外模式虽然并不具物理存在,但是也能通过映射而获得其存在的实体,同时两级映射也保证了数据库系统中数据的独立性,亦即数据的物理组织改变与逻辑概念级改变,并不影响用户外模式的改变,它只要调整映射方式而不必改变用户模式。

  1.概念模式到内模式的映射

  该映射给出了概念模式中数据的全局逻辑结构到数据的物理存储结构间的对应关系,此种映射一般由DBMS实现。

  2.外模式到概念模式的映射

  概念模式是一个全局模式而外模式则是用户的局部模式,一个概念模式中可以定义多个外模式,而每个外模式是概念模式的一个基本视图。外模式到概念模式的映射给出了外模式与概念模式的对应关系,这种映射一般由DBMS实现。

十、数据库事务的四大特性

⑴ 原子性(Atomicity)

  原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

⑵ 一致性(Consistency)

  一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

  拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。

⑶ 隔离性(Isolation)

  隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

  即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。

  关于事务的隔离性数据库提供了多种隔离级别,稍后会介绍到。

⑷ 持久性(Durability)

  持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

  例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。

  

  以上介绍完事务的四大特性(简称ACID),现在重点来说明下事务的隔离性,当多个线程都开启事务操作数据库中的数据时,数据库系统要能进行隔离操作,以保证各个线程获取数据的准确性,在介绍数据库提供的各种隔离级别之前,我们先看看如果不考虑事务的隔离性,会发生的几种问题:

1. 脏读:脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。当一个事务正在多次修改某个数据,而在这个事务中这多次的修改都还未提交,这时一个并发的事务来访问该数据,就会造成两个事务得到的数据不一致。例如:用户A向用户B转账100元,对应SQL命令如下

update account set money=money+100 where name=’B’; (此时A通知B) update account set money=money - 100 where name=’A’;

  当只执行第一条SQL时,A通知B查看账户,B发现确实钱已到账(此时即发生了脏读),而之后无论第二条SQL是否执行,只要该事务不提交,则所有操作都将回滚,那么当B以后再次查看账户时就会发现钱其实并没有转。

2. 不可重复读

  不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。

  例如事务T1在读取某一数据,而事务T2立马修改了这个数据并且提交事务给数据库,事务T1再次读取该数据就得到了不同的结果,发送了不可重复读。

  不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。

  在某些情况下,不可重复读并不是问题,比如我们多次查询某个数据当然以最后查询得到的结果为主。但在另一些情况下就有可能发生问题,例如对于同一个数据A和B依次查询就可能不同,A和B就可能打起来了……

3. 虚读(幻读)

  幻读是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。

  幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。

现在来看看MySQL数据库为我们提供的四种隔离级别:

  ① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。

  ② Repeatable read (可重复读):可避免脏读、不可重复读的发生。

  ③ Read committed (读已提交):可避免脏读的发生。

  ④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。

  以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别,当然级别越高,执行效率就越低。像Serializable这样的级别,就是以锁表的方式(类似于Java多线程中的锁)使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。在MySQL数据库中默认的隔离级别为Repeatable read (可重复读)。

  在MySQL数据库中,支持上面四种隔离级别,默认的为Repeatable read (可重复读);而在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。

  在MySQL数据库中查看当前事务的隔离级别:

select @@tx_isolation;

十一、锁与死锁

1. 锁的定义:锁是数据库中在并发操作情形下保护资源的机制。通常(具体要看锁兼容性)只有锁的拥有者才能对被锁的资源进行操作,从而保证数据一致性

2. 锁的类型:

1)共享锁:Shared Lock,S Lock. 通常情况下,读取数据时会对数据加上S Lock。

2)排它锁: Exclusive Lock,X Lock。对数据进行更改(insert update,delete)时加X Lock

3)更新锁:Update Lock,U Lock(或叫UPD Lock)。通常对数据进行Update操作会加U锁。查找数据时会加U锁,找到后对数据进行更改时在转换为X锁。U锁是为了防止在并发对数据进行更新时出现死锁,因为如果先加S锁再转换为X锁,由于S锁和S锁兼容,但X锁和S锁不兼容,所以有可能出现死锁。

4)意向锁:Intent Lock(例如:IX,IU,IS),是指对被锁定的资源的上层资源加锁。意向锁是为了提高锁的效率。例如对行加X锁,会对表加IX锁(意向排他锁),如果其他线程或事物想对该表加X锁,就不用逐行检查是否有其他所,只需检查是否有IX锁(或其他意向锁)

3. 锁在事务中的持续时间:

不同的事务隔离级别下,锁有不同的持续时间。(单一个SQL语句也是一个事物,称为“自动提交事务”,用begin tran/commit声明的是显式事务)

  1. Read uncommitted: select不会加锁(no lock),但更新会加U锁并持续到事务介绍
  2. Read committed:select加S锁,读完释放。U锁和X锁持续到事务结束
  3. Repeatable Read : select加S锁,但读完不释放,和U锁,X锁一样持续到事务结束。
  4. Serializable :select会加范围锁,读完不释放,和U锁,X锁一样持续到事务结束。

4. 死锁:死锁就是两个或多个会话(SPID)相互请求对方持有的锁资源,导致循环等待的情况

5. 解决死锁:

前些天写一个存储过程,存储过程中使用了事务,后来我把一些代码注释掉来进行调试找错,突然发现一张表被锁住了,原来是创建事务的代码忘记注释掉。本文表锁住了的解决方法。 其实不光是上面描述的情况会锁住表,还有很多种场景会使表放生死锁,解锁其实很简单,下面用一个示例来讲解: 1 首先创建一个测试用的表:

CREATE TABLE Test ( TID INT IDENTITY(1,1) )

2 执行下面的SQL语句将此表锁住:

SELECT * FROM Test WITH (TABLOCKX)

3 通过下面的语句可以查看当前库中有哪些表是发生死锁的:

SELECT request_session_id spid,OBJECT_NAME(resource_associated_entity_id)tableName FROM sys.dm_tran_locks WHERE resource_type='OBJECT '

4 上面语句执行结果如下:

  • spid :被锁进程ID。
  • tableName:发生死锁的表名。

5 只需要使用kill关键字来杀掉被锁的进程ID就可以对表进行解锁:

KILL 52

十二、数据仓库

from:https://blog.csdn.net/trigl/article/details/68944434

官方定义

数据仓库是一个面向主题的、集成的、随时间变化的、但信息本身相对稳定的数据集合,用于对管理决策过程的支持。

这个定义的确官方,但是却指出了数据仓库的四个特点。

特点

面向主题:数据仓库都是基于某个明确主题,仅需要与该主题相关的数据,其他的无关细节数据将被排除掉 

集成的:从不同的数据源采集数据到同一个数据源,此过程会有一些ETL操作 

随时间变化:关键数据隐式或显式的基于时间变化 

信息本身相对稳定:数据装入以后一般只进行查询操作,没有传统数据库的增删改操作

个人理解

数据仓库就是整合多个数据源的历史数据进行细粒度的、多维的分析,帮助高层管理者或者业务分析人员做出商业战略决策或商业报表。

事实表和维表

事实表是用来记录分析的内容的全量信息的,包含了每个事件的具体要素,以及具体发生的事情。事实表中存储数字型ID以及度量信息。

维表则是对事实表中事件的要素的描述信息,就是你观察该事务的角度,是从哪个角度去观察这个内容的。

事实表和维表通过ID相关联,如图所示:

这里写图片描述

3.2 数据仓库设计步骤

1、确定主题

主题与业务密切相关,所以设计数仓之前应当充分了解业务有哪些方面的需求,据此确定主题

2、确定量度

在确定了主题以后,我们将考虑要分析的技术指标,诸如年销售额之类。量度是要统计的指标,必须事先选 

择恰当,基于不同的量度将直接产生不同的决策结果。

3、确定数据粒度

考虑到量度的聚合程度不同,我们将采用“最小粒度原则”,即将量度的粒度设置到最小。例如如果知道某些数据细分到天就好了,那么设置其粒度到天;但是如果不确定的话,就将粒度设置为最小,即毫秒级别的。

4、确定维度

设计各个维度的主键、层次、层级,尽量减少冗余。

5、创建事实表

事实表中将存在维度代理键和各量度,而不应该存在描述性信息,即符合“瘦高原则”,即要求事实表数据条数尽量多(粒度最小),而描述性信息尽量少。

十三、in和exist

from:https://www.cnblogs.com/emilyyoucan/p/7833769.html

in:确定给定的值是否与子查询或列表中的值相匹配。in在查询的时候,首先查询子查询的表,然后将内表和外表做一个笛卡尔积,然后按照条件进行筛选。所以相对内表比较小的时候,in的速度较快

exist:指定一个子查询,检测行的存在。遍历循环外表,然后看外表中的记录有没有和内表的数据一样的,匹配上就将结果放入结果集中。外表小时建议使用exist。

in 和 exists的区别: 如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in, 反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists。其实我们区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了 ,另外IN时不对NULL进行处理。

in 是把外表和内表作hash 连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。一直以来认为exists比in效率高的说法是不准确的。

十四、group_concat()

使用group_concat()和group by显示相同名字的人的id号:

猜你喜欢

转载自blog.csdn.net/u013382288/article/details/81415051
今日推荐