第十章 数据库专题
10.1. 如何获取以后数据库版本?
答:运行 SQL SERVER 服务管理器,在任务栏小托盘处,右键单击管理器图标,选“对于”,在弹出的窗口中,对照下面的信息便可获取。
10.2. InnoDB 题
一张自增表外面总共有 7 条数据,删除了最初 2 条数据,重启 MySQL 数据库,又插入了一条数据,此时 id 是几?
答:表类型如果是 MyISAM,那 id 就是 8。
表类型如果是 InnoDB,那 id 就是 6。
10.3. 序列的作用
Oracle 应用序列来生成惟一编号,用来解决一个表中自增字段。Oracle 序列是原子对象,并且是统一的。也就是说,一旦您拜访一个序列号,Oracle 将在解决下一个申请之前主动递增下一个编号,从而确保不会呈现反复值。
10.4. 触发器的作用:
触发器是一中非凡的存储过程,次要是通过事件来触发而被执行的。它能够强化束缚,来保护数据的完整性和一致性,能够跟踪数据库内的操作从而不容许未经许可的更新和变动。能够联级运算。如,某表上的触发器上蕴含对另一个表的数据操作,而该操作又会导致该表触发器被触发。
10.5. 什么是存储过程?用什么来调用?
存储过程是一个预编译的 SQL 语句,长处是容许模块化的设计,就是说只需创立一次,当前在该程序中就能够调用屡次。如果某次操作须要执行屡次 SQL,应用存储过程比单纯 SQL 语句执行要快。
调用:
1)能够用一个命令对象来调用存储过程。
2)能够供内部程序调用,比方:java 程序。
10.6. 存储过程的优缺点?
长处:
存储过程是预编译过的,执行效率高。
存储过程的代码间接寄存于数据库中,通过存储过程名间接调用,缩小网络通讯。
安全性高,执行存储过程须要有肯定权限的用户。
存储过程能够重复使用,可缩小数据库开发人员的工作量。
毛病:
移植性差
10.7. 存储过程与函数的区别
存储过程 函数用于在数据库中实现特定的操作或者工作(如插入、删除等)用于特定的数据(如抉择)程序头部申明用 procedure 程序头部申明用 function 程序头部申明时不需形容返回类型 程序头部申明时要形容返回类型,而且 PL/SQL 块中至多要包含一个无效的 return 语句能够应用 in/out/in out 三种模式的参数能够应用 in/out/in out 三种模式的参数可作为一个独立的 PL/SQL 语句来执行 不能独立执行,必须作为表达式的一部分调用能够通过 out/in out 返回零个或多个值通过 return 语句返回一个值,且改值要与申明局部统一,也能够是通过 out 类型的参数带出的变量 SQL 语句 (DML 或 SELECT) 中不可调用存储过程 SQL 语句 (DML 或 SELECT) 中能够调用函数
10.8. 索引的作用?和它的长处毛病是什么?
索引:索引就一种非凡的查问表,数据库的搜寻能够利用它减速对数据的检索。
长处:它很相似与现实生活中书的目录,不须要查问整本书内容就能够找到想要的数据。索引能够是惟一的,创立索引容许指定单个列或者是多个列。
毛病:是它减慢了数据录入的速度,同时也减少了数据库的尺寸大小。
10.9. 什么样的字段适宜建索引
惟一、不为空、常常被查问的字段
10.10. 索引类型有哪些?
逻辑上:
1.Single column 单行索引
2.Concatenated 多行索
3.Unique 惟一索引
4.NonUnique 非惟一索引
5.Function-based 函数索引
6.Domain 域索引 物理上:
7.Partitioned 分区索引
8.NonPartitioned 非分区索引
9.tree:
Normal 失常型 B 树
Rever Key 反转型 B 树 Bitmap 位图索引
10.11. 什么是数据库事务?
答案:
单个逻辑单元执行的一系列操作, 这些操作要么全做要么全不做, 是不可分割的. 事务的开始和完结用户是能够管制的, 如果没管制则由数据库默认的划分事务. 事务具备以下性质:
(1) 原子性:
指一个事务要么全执行, 要么全不执行. 也就是说一个事务不可能执行到一半就进行了.
(2) 一致性:
指事务的运行并不扭转数据库中的一致性. 比方 a+b=10;a 扭转了,b 也应该随之扭转.
(3) 独立性:- 63 –
两个以上的事务不会呈现交替运行的状态, 因为这样可能导致数据的不统一
(4) 持久性:
事务运行胜利之后数据库的更新是永恒的
10.12. SQL 中别离有几种事务?各有什么特点?:
答:4 种事务:
主动提交事务
隐式事务特点
显示事务
分布式事务
主动提交事务特点:每条独自语句都是一个事务。
隐式事务特点:前一个事务实现时新事务隐式启动,每个事务仍以 COMMIT 或 ROLLBACK 语句、显示完结。
显示事务特点:每个事务均已 BEGIN TRANSACTION 语句显示开始,以 COMMIT 或 ROLLBACK 语句显示完结。
分布式事务特点:逾越多个服务器的事务
10.13. 什么是回滚?
为了保障在应用程序、数据库或零碎呈现谬误后,数据库可能被还原,以保障数据库的完整性,所以须要进行回滚。回滚(rollback)就是在事务提交之前将数据库数据恢复到事务批改之前数据库数据状态。
10.14. 什么是事务?什么是锁?
事务:
事务就是被绑定在一起作为一个逻辑工作单元的 SQL 语句分组,如果任何一个语句操作失败那么整个操作就被失败,当前操作就会回滚到操作前状态,或者是上有个节点。为了确保要么执行,要么不执行,就能够应用事务。要将有组语句作为事务思考,就须要通过 ACID 测试,即原子性,一致性,隔离性和持久性。
锁:
在所有的 DBMS 中,锁是实现事务的要害,锁能够保障事务的完整性和并发性。与现
实生存中锁一样,它能够使某些数据的拥有者,在某段时间内不能应用某些数据或数据结构。
当然锁还分级别的。- 64 –
10.15. 什么是封闭?封闭的根本类型有哪几种?含意是什么?
封闭:
所谓封闭就是当一个事务在对某个数据对象(能够是数据项、记录、数据集、以至整个数据库)进行操作之前,必须取得相应的锁,以保证数据操作的正确性和一致性。
根本的封闭类型有两种:排它锁和共享锁
(1)排它锁:排它锁又称写锁,简称为 X 锁,其采纳的原理是禁止并发操作。
(2)共享锁:共享锁又称读锁,, 简称为 S 锁,其采纳的原理是容许其余用户对同一数
据对象进行查问,但不能对该数据对象进行批改。
10.16. sql 数据库里锁是什么以及分类介绍
目前的 C/S,B/S 构造都是多用户拜访数据库, 每个工夫点会有成千上万个 user 来拜访 DB, 其中也会同时存取同一份数据, 会造成数据的不一致性或者读脏数据,数据库必须有锁的机制来确保数据的残缺和一致性
6 种锁的类型:
(1) 共享锁:
共享锁用于所有的只读数据操作.
(2) 批改锁:
批改锁在批改操作的初始化阶段用来锁定可能要被批改的资源,这样能够防止应用共享
锁造成的死锁景象
(3) 独占锁:
独占锁是为批改数据而保留的。它所锁定的资源,其余事务不能读取也不能批改。独占
锁不能和其余锁兼容。
(4) 架构锁
构造锁分为构造批改锁(Sch-M)和构造稳固锁(Sch-S)。执行表定义语言操作时,
SQLServer 采纳 Sch-M 锁,编译查问时,SQLServer 采纳 Sch-S 锁。
(5) 意向锁
意向锁阐明 SQL Server 有在资源的低层取得共享锁或独占锁的动向。
(6) 批量批改锁
批量复制数据时应用批量批改锁
10.17. 什么是死锁?产生死锁的必要条件。
1)在同时处于期待状态的两个或多个事务中,每个事务都在期待其中另一个事务解除封闭,它能力继续执行上来,后果造成任何一个事务都无奈继续执行,这种状态称为死锁.
2)产生死锁的必要条件有以下四条:
(1)互斥条件:一个数据对象一次只能被一个事务所应用,即对数据的封闭采纳排它式;
(2)不可抢占条件:一个数据对象只能被占有它的事务所开释,而不能被别的事务强行抢占
(3)互斥条件:一个数据对象一次只能被一个事务所应用,即对数据的封闭用排它式;
(4)不可抢占条件:一个数据对象只能被占有它的事务所开释,而不能被别的事务强行抢占
10.18. 什么叫视图?游标是什么?
视图:
是一种虚构的表,具备和物理表雷同的性能。能够对视图进行增,改,查,操作,试图通常是有一个表或者多个表的行或列的子集。对视图的批改会影响根本表。它使得咱们获取数据更容易,相比多表查问。
游标:
是对查问进去的后果集作为一个单元来无效的解决。游标能够定在该单元中的特定行,从后果集的以后行检索一行或多行。能够对后果集以后行做批改。个别不应用游标,然而须要逐条解决数据的时候,游标显得非常重要。
10.19. 应用游标的根本步骤有哪些?
- 申明游标
- 关上游标
- 读取游标中的数据
- 敞开游标
- 开释游标
10.20. 视图的优缺点
长处:
对数据库的拜访,因为视图能够有选择性的选取数据库里的一部分。用户通过简略的查问能够从简单查问中失去后果。保护数据的独立性,试图可从多个表检索数据。对于雷同的数据可产生不同的视图。
毛病:
性能:查问视图时,必须把视图的查问转化成对根本表的查问,如果这个视图是由一个简单的多表查问所定义,那么,那么就无奈更改数据。
10.21. 列举几种表连贯形式, 有什么区别?
内连贯、自连贯、外连贯(左、右、全)、穿插连贯
内连贯:只有两个元素表相匹配的能力在后果集中显示。
外连贯:左外连贯: 右边为驱动表,驱动表的数据全副显示,匹配表的不匹配的不会显示。
右外连贯: 左边为驱动表,驱动表的数据全副显示,匹配表的不匹配的不会显示。
全外连贯:连贯的表中不匹配的数据全副会显示进去。
穿插连贯:笛卡尔效应,显示的后果是链接表数的乘积。
10.22. 主键和外键的区别?
1. 主键在本表中是惟一的、不可唯空的。
2. 外键能够反复能够唯空。
3. 外键和另一张表的主键关联,不能创立对应表中不存在的外键。
10.23. 在数据库中查问语句速度很慢,如何优化?
- 建索引
- 缩小表之间的关联
- 优化 sql,尽量让 sql 很快定位数据,不要让 sql 做全表查问,应该走索引, 把数据 量大的表排在后面
- 简化查问字段,没用的字段不要,曾经对返回后果的管制,尽量返回大量数据
- 尽量用 PreparedStatement 来查问,不要用 Statement
10.24. 数据库三范式是什么?
(1)第一范式(1NF):
所谓第一范式(1NF)是指在关系模型中,对于增加的一个标准要求,所有的域都应该
是原子性的,即数据库表的每一列都是不可分割的原子数据项,而不能是汇合,数组,记录
等非原子数据项。
(2)第二范式(2NF):- 67 –
在 1NF 的根底上,非码属性必须齐全依赖于候选码(在 1NF 根底上打消非主属性对主
码的局部函数依赖)。
第二范式(2NF)是在第一范式(1NF)的根底上建设起来的,即满足第二范式(2NF)
必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或记录必须可
以被惟一地区分。选取一个能辨别每个实体的属性或属性组,作为实体的惟一标识。
(3)第三范式(3NF):
第三范式(3NF)是第二范式(2NF)的一个子集,即满足第三范式(3NF)必须满足
第二范式(2NF)。简而言之,第三范式(3NF)要求一个关系中不蕴含已在其它关系已包
含的非主关键字信息。
10.25. union 和 union all 有什么不同?
Union:
UNION 在进行表链接后会筛选掉反复的记录,所以在表链接后会对所产生的后果集进
行排序运算,删除反复的记录再返回后果。理论大部分利用中是不会产生反复的记录,最常
见的是过程表与历史表 UNION。
union all:
UNION ALL 只是简略的将两个后果合并后就返回。这样,如果返回的两个后果集中有
反复的数据,那么返回的后果集就会蕴含反复的数据了。从效率上说,UNION ALL 要比
UNION 快很多,所以,如果能够确认合并的两个后果集中不蕴含反复的数据的话,那么就
应用 UNION ALL。
10.26. CHAR 和 VARCHAR 的区别是什么?
答:
(1)CHAR 的长度是固定的,而 VARCHAR 的长度是能够变动的。
(2)CHAR 的效率比 VARCHAR 的效率稍高。
(3)目前 VARCHAR 是 VARCHAR 的同义词。
10.27. Varchar2 和 varchar 有什么区别?
Char 的长度是固定的,而 varchar2 的长度是能够变动的,比方,存储字符串“abc”
对于 char(20),示意你存储的字符将占 20 个字节,蕴含 17 个空,而同样的 varchar2(20)只占了 3 个字节,20 只是最大值,当你存储的字符小于 20 时,按理论长度存储。char 的效率要被 varchar2 的效率高。目前 varchar 是 varchar2 的同义词,工业规范的 varchar 类型能够存储空字符串,然而 oracle 不能这样做,只管它保留当前这样做的权力。Oracle 本人开发了一个数据类型 varchar2, 这个类型不是一个规范的 varchar,他将在数据库中 varchar 列能够存储空字符串的个性改为存储 null 值,如果你想有向后兼容的能力,oracle 倡议应用 varchar2 而不是 varchar
10.28. float 和 double 的区别是什么?
(1)范畴
float 和 double 的范畴是由指数的位数来决定的。
(2)精度
float 和 double 的精度是由尾数的位数来决定的。浮点数在内存中是按迷信计数法来
存储的,其整数局部始终是一个隐含着的“1”,因为它是不变的,故不能对精度造成影响。
10.29. Oracle 和 Mysql 的区别?
1)库函数不同。
2)Oracle 是用表空间来治理的,Mysql 不是。
3)显示以后所有的表、用户、扭转连贯用户、显示以后连贯用户、执行内部脚本的语句的不同。
4)分页查问时候时候,mysql 用 limit oracle 用 rownum
10.30. sql 语句应该思考哪些安全性?
(1)避免 sql 注入,对特殊字符进行本义,过滤或者应用预编译的 sql 语句绑定变量。
(2)最小权限准则,特地是不要用 root 账户,为不同的类型的动作或者组建应用不同的账户。
(3)当 sql 运行出错时,不要把数据库返回的错误信息全副显示给用户,以避免透露服务器和数据库相干信息。
10.31. 什么是内存透露?
答:个别咱们所说的内存透露指的是堆内存的透露。堆内存是程序从堆中为其调配的,大小任意的,应用完后要显示开释内存。当应用程序用关键字 new 等创建对象时,就从堆中为它调配一块内存,应用完后程序调用 free 或者 delete 开释该内存,否则就说该内存就不能被应用,咱们就说该内存被透露了。
10.32. Delete、truncate、drop 都是删除语句,它们有什么别离?
- delete 属于 DML 语句,删除数据,保留表构造,须要 commit,能够回滚,如果数据量大,很慢。
- truncate 属于 DDL 语句,删除所有数据,保留表构造,主动 commit,不能够回滚,一次全副删除所有数据,速度绝对较快。
- Drop 属于 DDL 语句,删除数据和表构造, 不须要 commit,删除速度最快。
10.33. order by 和 groupby 的区别
order by:排序查问、asc 升序、desc 降序
group by:分组查问、having 只能用于 groupby 子句、作用于组内,having 条件子句能够间接跟函数表达式。应用 group by 子句的查问语句须要应用聚合函数。
10.34. 何谓乐观锁与乐观锁
乐观锁对应于生存中乐观的人总是想着事件往好的方向倒退,乐观锁对应于生存中乐观的人总是想着事件往坏的方向倒退。这两种人各有优缺点,不能不以场景而定说一种人好于另外一种人。
乐观锁
总是假如最坏的状况,每次去拿数据的时候都认为他人会批改,所以每次在拿数据的时候都会上锁,这样他人想拿这个数据就会阻塞直到它拿到锁(共享资 源每次只给一个线程应用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比方行锁,表锁 等,读锁,写锁等,都是在做操作之前先上锁。Java 中 synchronized 和 ReentrantLock 等独占锁就是乐观锁思维的实现。
乐观锁
总是假如最好的状况,每次去拿数据的时候都认为他人不会批改,所以不会上锁,然而在更新的时候会判断一下在此期间他人有没有去更新这个数据,能够 应用版本号机制和 CAS 算法实现。乐观锁实用于多读的利用类型,这样能够提 高吞吐量,像数据库提供的相似于 write_condition 机制,其实都是提供的乐 观锁。在 Java 中 java.util.concurrent.atomic 包上面的原子变量类就是应用了 乐观锁的一种实现形式 CAS 实现的。
两种锁的应用场景
从上面对两种锁的介绍,咱们晓得两种锁各有优缺点,不可认为一种好于另一 种,像乐观锁实用于写比拟少的状况下(多读场景),即抵触真的很少产生的 时候,这样能够省去了锁的开销,加大了零碎的整个吞吐量。但如果是多写的 状况,个别会常常产生抵触,这就会导致下层利用会一直的进行 retry,这样反 倒是升高了性能,所以个别多写的场景下用乐观锁就比拟适合。
乐观锁常见的两种实现形式
乐观锁个别会应用版本号机制或 CAS 算法实现。
版本号机制
个别是在数据表中加上一个数据版本号 version 字段,示意数据被批改的次 数,当数据被批改时,version 值会加一。当线程 A 要更新数据值时,在读取数 据的同时也会读取 version 值,在提交更新时,若方才读取到的 version 值为当 前数据库中的 version 值相等时才更新,否则重试更新操作,直到更新胜利。
举一个简略的例子:假如数据库中帐户信息表中有一个 version 字段,以后值 为 1;
而以后帐户余额字段(balance)为 $100。
- 操作员 A 此时将其读出(version=1),并从其帐户余额中扣除 $50
($100-$50)。
- 在操作员 A 操作的过程中,操作员 B 也读入此用户信息(version=1),并从
其帐户余额中扣除 $20($100-$20)。
- 操作员 A 实现了批改工作,将数据版本号加一(version=2),连同帐户扣除后余额(balance=$50),提交至数据库更新,此时因为提 交数据版本大于数据库记录以后版本,数据被更新,数据库记录 version 更新为 2。
- 操作员 B 实现了操作,也将版本号加一(version=2)试图向数据库 提交数据(balance=$80),但此时比对数据库记录版本时发现,操 作员 B 提交的数据版本号为 2,数据库记录以后版本也为 2,不满 足“提交版本必须大于记录以后版本能力执行更新“的乐观锁策略,因而,操作员 B 的提交被驳回。这样,就防止了操作员 B 用基于 version=1 的旧数据批改的后果笼罩操作员 A 的操作后果的可能。
- CAS 算法
即 compare and swap(比拟与替换),是一种有名的无锁算法。无锁编程,即不应用锁的状况下实现多线程之间的变量同步,也就是在没有线程被阻塞的 状况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。CAS 算法波及到三个操作数须要读写的内存值 V 进行比拟的值 A 拟写入的新值 B 当且仅当 V 的值等于 A 时,CAS 通过原子形式用新值 B 来更新 V 的值,否则不会执行任何操作(比拟和替换是一个原子操作)。个别状况下是一个自旋操作,即一直的重试。
乐观锁的毛病
ABA 问题是乐观锁一个常见的问题
1 ABA 问题
如果一个变量 V 首次读取的时候是 A 值,并且在筹备赋值的时候查看到它依然 是 A 值,那咱们就能阐明它的值没有被其余线程批改过了吗?很显著是不能的,因为在这段时间它的值可能被改为其余值,而后又改回 A,那 CAS 操作就 会误认为它素来没有被批改过。这个问题被称为 CAS 操作的 “ABA” 问题。
JDK 1.5 当前的 AtomicStampedReference 类就提供了此种能力,其中的 compareAndSet 办法就是首先查看以后援用是否等于预期援用,并且以后标记是 否等于预期标记,如果全副相等,则以原子形式将该援用和该标记的值设置为 给定的更新值。
2 循环工夫长开销大
自旋 CAS(也就是不胜利就始终循环执行直到胜利)如果长时间不胜利,会给 CPU 带来十分大的执行开销。如果 JVM 能反对处理器提供的 pause 指令那么 效率会有肯定的晋升,pause 指令有两个作用,第一它能够提早流水线执行指 令(de-pipeline), 使 CPU 不
会耗费过多的执行资源,提早的工夫取决于具体 实现的版本,在一些处理器上延迟时间是零。第二它能够防止在退出循环的时 候因内存程序抵触(memory order violation)而引起 CPU 流水线被清空(CPU pipeline flush),从而进步 CPU 的执行效率。
3 只能保障一个共享变量的原子操作
CAS 只对单个共享变量无效,当操作波及跨多个共享变量时 CAS 有效。然而 从 JDK1.5 开始,提供了 AtomicReference 类来保障援用对象之间的原子性,你 能够把多个变量放在一个对象里来进行 CAS 操作. 所以咱们能够应用锁或者利 用 AtomicReference 类把多个共享变量合并成一个共享变量来操作。CAS 与 synchronized 的应用情景
简略的来说 CAS 实用于写比拟少的状况下(多读场景,抵触个别较少),synchronized 实用于写比拟多的状况下(多写场景,抵触个别较多)
1. 对于资源竞争较少(线程抵触较轻)的状况,应用 synchronized 同步锁 进行线程阻塞和唤醒切换以及用户态内核态间的切换操作额定节约耗费 cpu 资源;而 CAS 基于硬件实现,不须要进入内核,不须要切换线程,操作自旋几率较少,因而能够取得更高的性能。
- 对于资源竞争重大(线程抵触重大)的状况,CAS 自旋的概率会比拟 大,从而节约更多的 CPU 资源,效率低于 synchronized。
补充:Java 并发编程这个畛域中 synchronized 关键字始终都是元老级的角 色,很久之前很多人都会称它为“重量级锁”。然而,在 JavaSE 1.6 之后进行了 次要包含为了缩小取得锁和开释锁带来的性能耗费而引入的 偏差锁 和 轻量级 锁 以及其它各种优化之后变得在某些状况下并不是那