1 列举常见的关系型数据库和非关系型都有哪些?
1.1 关系型数据库(需要有表结构)
表和表、表和字段、数据和数据存在着关系。常用的有MySQL、oracle、SQL server、db2、sybase等
优点:
- 易于维护:都是使用表结构,格式一致;
- 使用方便:SQL语言通用,可用于复杂查询;
- 复杂操作:支持SQL。可用一个表以及多个表之间非常复杂的查询。
缺点:
- 读写性能比较差,尤其是海量数据的高效率读写;
- 固定的表结构,灵活度稍欠;
- 高并发读写需求,对传统关系型数据库来说,硬盘I/O是一个很大的麻烦
1.2 非关系数据库
严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。
优点:
- 格式灵活:存储数据的格式可以是key:value形式、文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型;
- 速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系数据库只能使用硬盘;
- 高扩展性;
- 成本低:nosql数据库部署简单,基本都是开源软件。
缺点:
- 不提供SQL支持,学习和使用成本较高;
- 无事务处理;
- 数据结构相对复杂,复杂查询方面稍欠。
非关系型数据库的分类比较:
-
文档型
-
key-value型
-
列式数据库
-
图形数据库
2 什么是数据库,数据库管理系统,数据库系统,数据库管理员?
- 数据库:数据库(DataBase简称DB)就是信息的集合或者说数据库是由数据库管理系统管理的数据的集合。
- 数据库管理系统 : 数据库管理系统(Database Management System 简称DBMS)是一种操纵和管理数据库的大型软件,通常用语用于建立、使用和维护数据库。
- 数据库系统 : 数据库系统(Data Base System,简称DBS)通常由软件、数据库和数据管理员(DBA)组成。
- 数据库管理员 : 数据库管理员(Database Administrator,简称DBA)负责全面管理和控制数据库系统。 数据库系统基本构成如下图所示:
3 什么是元组,码,候选码,主码,外码,主属性,非主属性?
- 元组 : 元组(tuple)是关系数据库中的基本概念,关系是一张表,表中的每行(即数据库中的每条记录)就是一个元组,每列就是一个属性。 在二维表里,元组也称为行。 码 :码就是能唯一标识实体的属性,对应表中的列。
- 候选码 : 若关系中的某一属性或属性组的值能唯一的标识一个元组,而其任何、子集都不能再标识,则称该属性组为候选码。例如:在学生实体中,“学号”是能唯一的区分学生实体的,同时又假设“姓名”、“班级”的属性组合足以区分学生实体,那么{学号}和{姓名,班级}都是候选码。
- 主码 : 主码也叫主键。主码是从候选码中选出来的。 一个实体集中只能有一个主码,但可以有多个候选码。
- 外码 : 外码也叫外键。如果一个关系中的一个属性是另外一个关系中的主码则这个属性为外码。
- 主属性 : 候选码中出现过的属性称为主属性。比如关系 工人(工号,身份证号,姓名,性别,部门).显然工号和身份证号都能够唯一标示这个关系,所以都是候选码。工号、身份证号这两个属性就是主属性。如果主码是一个属性组,那么属性组中的属性都是主属性。
- 非主属性: 不包含在任何一个候选码中的属性称为非主属性。比如在关系——学生(学号,姓名,年龄,性别,班级)中,主码是“学号”,那么其他的“姓名”、“年龄”、“性别”、“班级”就都可以称为非主属性。
4 主键和外键有什么区别?
- 主键(主码) :主键用于唯一标识一个元组,不能有重复,不允许为空。一个表只能有一个主键。
- 外键(外码) :外键用来和其他表建立联系用,外键是另一表的主键,外键是可以有重复的,可以是空值。一个表可以有多个外键。
5 内连接与外连接
5.1 MySQL内连接(inner join on)
MySQL的内连接使用inner join on,它的效果跟使用where是一样的,如果联结的是两个表,那么需要左右的条件或者说字段是需要完全匹配的。
5.2 MySQL外连接(left,right)
- 外连接包含左右连接
- 左连接的结果是除了匹配条件的数据还包含左边表中的所有数据
- 右连接的结果是除了匹配条件的数据还包含右边表中的所有数据
6 什么是ER图?
E-R图也称实体-联系图(Entity Relationship Diagram),提供了表示实体类型、属性和联系的方法,用来描述现实世界的概念模型。 它是描述现实世界关系概念模型的有效方法。 是表示概念关系模型的一种方式。
下图是一个学生选课的ER图,每个学生可以选若干门课程,同一门课程也可以被若干人选择,所以它们之间的关系是多对多(M:N)。另外,还有其他两种关系是:1对1(1:1)、1对多(1:N)。
我们试着将上面的ER图转换成数据库实际的关系模型(实际设计中,我们通常会将任课教师也作为一个实体来处理):
7 数据库范式了解吗?
7.1 一些重要的概念:
- 函数依赖(functional dependency)
若在一张表中,在属性(或属性组)X的值确定的情况下,必定能确定属性Y的值,那么就可以说Y函数依赖于X,写作 X → Y。
- 部分函数依赖(partial functional dependency)
如果X→Y,并且存在X的一个真子集X0,使得X0→Y,则称Y对X部分函数依赖。比如学生基本信息表R中(学号,身份证号,姓名)当然学号属性取值是唯一的,在R关系中,(学号,身份证号)->(姓名),(学号)->(姓名),(身份证号)->(姓名);所以姓名部分函数依赖与(学号,身份证号);
- 完全函数依赖(Full functional dependency)
在一个关系中,若某个非主属性数据项依赖于全部关键字称之为完全函数依赖。比如学生基本信息表R(学号,班级,姓名)假设不同的班级学号有相同的,班级内学号不能相同,在R关系中,(学号,班级)->(姓名),但是(学号)->(姓名)不成立,(班级)->(姓名)不成立,所以姓名完全函数依赖与(学号,班级);
- 传递函数依赖
在关系模式R(U)中,设X,Y,Z是U的不同的属性子集,如果X确定Y、Y确定Z,且有X不包含Y,Y不确定X,(X∪Y)∩Z=空集合,则称Z传递函数依赖(transitive functional dependency) 于X。传递函数依赖会导致数据冗余和异常。传递函数依赖的Y和Z子集往往同属于某一个事物,因此可将其合并放到一个表中。比如在关系R(学号 ,姓名, 系名,系主任)中,学号 → 系名,系名 → 系主任,所以存在非主属性系主任对于学号的传递函数依赖。
7.2 1NF(第一范式)
属性(对应于表中的字段)不能再被分割,也就是这个字段只能是一个值,不能再分为多个其他的字段了。1NF是所有关系型数据库的最基本要求 ,也就是说关系型数据库中创建的表一定满足第一范式。
7.3 2NF(第二范式)
2NF在1NF的基础之上,消除了非主属性对于码的部分函数依赖。如下图所示,展示了第一范式到第二范式的过渡。第二范式在第一范式的基础上增加了一个列,这个列称为主键,非主属性都依赖于主键。
7.4 3NF(第三范式)
3NF在2NF的基础之上,消除了非主属性对于码的传递函数依赖 。符合3NF要求的数据库设计,基本上解决了数据冗余过大,插入异常,修改异常,删除异常的问题。比如在关系R(学号 ,姓名, 系名,系主任)中,学号 → 系名,系名 → 系主任,所以存在非主属性系主任对于学号的传递函数依赖,所以该表的设计,不符合3NF的要求。
7.5 总结
- 1NF:属性不可再分。
- 2NF:1NF的基础之上,消除了非主属性对于码的部分函数依赖。
- 3NF:3NF在2NF的基础之上,消除了非主属性对于码的传递函数依赖 。
8 数据库三大特性:
- 实体 :表
- 属性:表中的数据(字段)
- 关系 :表与表之间的关系
9 数据库五大约束:
- primary key:设置主键约束;
- UNIQUE:设置唯一性约束,不能有重复值;
- DEFAULT:默认值约束;
- NOT NULL:设置非空约束,该字段你能为空;
- FOREIGN KEY:设置外键约束。
10 MySQL常见的数据库引擎及比较?
- InnoDB 支持事务;支持表锁、行锁(for update) 表锁:select * from tb for update 行锁:select id,name from tb where id=2 for update
- Myisam:查询速度快;全文索引;支持表锁;
- NDB: 高可用、高性能、高可扩展性的数据库集群系统;
- Memory:默认使用的是哈希索引;
- BDB: 可替代InnoDB的事务引擎,支持COMMIT、ROLLBACK和其他事务特性;
- Merge: 允许MySQL DBA或开发人员将一系列等同的MyISAM表以逻辑方式组合在一起,并作为一个对象引用他们。对于诸如数据仓储等VLDB环境十分适合。
- Achive:为大量很少引用的历史、归档、或安全设计信息的存储和检索提供了完美的解决方案;
- Federated:能够将多个分离的MySQL服务器连接起来,从多个物理服务器创建一个逻辑数据库。十分适合于分布式环境或数据集市环境;
- Cluster:MySQL的簇式数据库引擎,尤其适合于具有高性能查找要求的应用程序,这类查找需求还要求具有更高的正常工作时间和可用性;
- Other: 其他存储引擎包括CSV(引用由逗号隔开的用作数据库表的文件),Blackhole(用于临时禁止对数据库的应用程序输入),以及Example引擎(可谓快速创建定制的插件式存储引擎提供帮助)。
InnoDB和MyisSam对比
MyISAM是MySQL的默认数据库引擎(5.5版之前),由早期的 ISAM (Indexed Sequential Access Method:有索引的顺序访问方法)所改良。虽然性能极佳,而且提供了大量的特性,包括全文索引、压缩、空间函数等,但MyISAM不支持事务和行级锁,而且最大的缺陷就是崩溃后无法安全恢复。不过,5.5版本之后,MySQL引入了InnoDB(另一种数据库引擎)。
大多数时候我们使用的都是InnoDB存储引擎,但是在某些情况下使用 MyISAM 也是合适的比如读密集的情况下。(如果你不介意 MyISAM 崩溃回复问题的话)。
两者的对比:
- 是否支持行级锁 : MyISAM 只有表级锁(table-level locking),而InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。
- 是否支持事务和崩溃后的安全恢复: MyISAM 强调的是性能,每次查询具有原子性,其执行数度比InnoDB类型更快,但是不提供事务支持。但是InnoDB 提供事务支持事务,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。
- 是否支持外键: MyISAM不支持,而InnoDB支持。
- 是否支持MVCC :仅 InnoDB 支持。应对高并发事务, MVCC比单纯的加锁更高效;MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个隔离级别下工作;MVCC可以使用 乐观(optimistic)锁 和 悲观(pessimistic)锁来实现;各数据库中MVCC实现并不统一。(MVCC出门左转)
11 事务相关
事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可滚回到原来的状态,从而保证数据库的数据完整性。
11.1 事务的特性:
- 原子性(Atomicity):事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功必须全部应用到数据库,如果数据操作失败则不能对数据库有任何的影响;
- 一致性(Consistency):是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致状态(确保数据库正确地改变状态后,成功提交事务);
- 隔离性(Isolation):是当多个用户并发访问数据库时,数据库为每一个用户开启的事务不能被其他事务的操作所干扰,多个并发事务之间要相互隔离(使事务操作彼此独立和透明的);
- 持久性(Durability):是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是数据库系统遇到故障的情况下也不会丢失提交事务的操作(确保提交的事务的结果或效果的系统出现故障的情况下仍然存在);
11.2 并发事务带来哪些问题?
在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对统一数据进行操作)。并发虽然是必须的,但可能会导致以下的问题。
- 脏读(Dirty read): 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。
- 丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。
- 不可重复读(Unrepeatableread): 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。
- 幻读(Phantom read): 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
不可重复度和幻读区别:
不可重复读的重点是修改,幻读的重点在于新增或者删除。
11.3 事务隔离级别有哪些?MySQL的默认隔离级别是?
11.3.1 四个隔离级别:
- READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
- READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
- REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
- SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| READ-UNCOMMITTED(读取未提交) | √ | √ | √ |
| READ-COMMITTED(读取已提交) | × | √ | √ |
| REPEATABLE-READ(可重复读) | × | × | √ |
| SERIALIZABLE(可串行化) | × | × | × |
MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。我们可以通过SELECT @@tx_isolation;命令来查看.
11.3.2 注意
与 SQL 标准不同的地方在于InnoDB 存储引擎在 REPEATABLE-READ(可重读)事务隔离级别下使用的是Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server)是不同的。所以说InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)** 已经可以完全保证事务的隔离性要求,即达到了 SQL标准的SERIALIZABLE(可串行化)隔离级别。
因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是READ-COMMITTED(读取提交内容):,但是你要知道的是InnoDB 存储引擎默认使用 REPEATABLE-READ(可重读)并不会有任何性能损失。
InnoDB 存储引擎在 分布式事务 的情况下一般会用到SERIALIZABLE(可串行化)隔离级别。
12 简述数据库设计中一对多和多对多的应用场景?
- FK(一对多):下拉框里面的数据就需要用FK关联另一张表; 实例:一个学生只属于一个班每一个班有多个学生
- M2M(多对多):多选的下拉框,或者CheckBox。 实例:一个学生可以选多门课程,一门课程也有多名学生
13 简述触发器、函数、视图、存储过程
- 触发器:对数据库某张表的增加、删除、修改前后定义一些操作;
- 函数:
- 触发函数:select
- 聚合函数:max/min/sum/avg
- 时间格式化:date_format
- 字符串拼接:concat
- 截取字符串:substring
- 返回字节个数:length
- 存储过程:将SQL语句保存到数据库中,并命名,以后在代码调用时,直接调用名称即可;
- 参数类型:
- in 只将参数穿进去
- out 只拿结果
- inout 既可以传,也可以取
- 参数类型:
存储过程在互联网公司应用不多,因为存储过程难以调试和扩展,而且没有移植性,还会消耗数据库资源。
- 函数和存储过程区别:
本质上没区别。只是函数有如:只能返回一个变量的限制。而存储过程可以返回多个。而函数是可以嵌入SQL中使用的,可以在select中调用,而存储过程不行。
- 视图:视图是一个虚拟表,不是真实存在的(只能查,不能改)
14 MySQL索引
由于索引的知识点太多,出门左转(MySQL索引小结)。
15 如何开启慢日志查询?
- 修改配置文件
slow_query_log = OFF # 是否开启慢日志记录
long_query_time = 2 # 时间限制,超过此时间,则记录
slow_query_log_file = /usr/slow.log # 日志文件
log_queries_not_using_indexes = OFF # 未使用索引的搜索是否记录
- 下面是开启
slow_query_log = ON
long_query_time = 2
log_queries_not_using_indexes = OFF
log_queries_not_using_indexes = ON
- 注意:
查看当前配置信息:show variables like '%query%'
修改当前配置:set global 变量名 = 值
16 数据库导入导出命令(结构+数据)?
- 导出现有数据库数据:(当有提示输入密码,-p就不用加密码)
mysqldump -u用户名 -p密码 数据库名称 > 导出文件路径 # 结构+数据
mysqldump -u用户名 -p密码 -d 数据库名称 > 导出文件 路径 # 结构
'--no-defaults':解决"unknown option --no-beep"错误
- 导入现有数据库数据:
mysqldump -uroot -p密码 数据库名称 < 文件路径
或者:进入数据库; source + 要导入数据库文件路径
17 数据库优化方案
- 创建数据表时把固定长度的放在前面
- 将固定数据放入内存:
例如 choice字段(django中有用到,数字1、2、3...对应相应内容)
- char 和 varchar 的区别(char可变,varchar不可变)
- 联合索引遵循最左前缀(从最左侧开始检索)
- 避免使用select *
- 读写分离
- 实现:两台服务器同步数据
- 利用数据库的主从分离:主,用于删除、修改、更新;从,用于查;
- 分库
当数据库中的表太多,将某些表分到不同的数据库,例如:1w张表时;
代价:连表查询
- 分表
- 水平分表:将某些列拆分到另一张表,例如:博客+博客详情;
- 垂直分表:将某些历史信息分到另外一张表中,例如:支付宝账单
- 加缓存
利用redis、memcache(常用数据放到缓存里,提高去取数据速度)
- 如果只想获得一条数据 select * from tb1 where name='alex' limit 1
下面补充一下数据库分片的两种常见方案:
- 客户端代理: 分片逻辑在应用端,封装在jar包中,通过修改或者封装JDBC层来实现。 当当网的 Sharding-JDBC 、阿里的TDDL是两种比较常用的实现。
- 中间件代理: 在应用和数据中间加了一个代理层。分片逻辑统一维护在中间件服务中。 我们现在谈的 Mycat 、360的Atlas、网易的DDB等等都是这种架构的实现。
18 简述MySQL的执行计划
explain + SQL语句
- 查看有没有命中索引,让数据库帮看看运行速度快不快
- SQL在数据库中的表现情况,通常用于SQL性能分析、优化等场景
19 在对name做了唯一索引的前提下,简述以下区别:
select * from tb1 where name = '小明' select * from tb1 where name = '小明' limit 1 没做唯一索引的话,前者查询会全表扫描,效率低些; limit 1,只要找到对应一条数据,就不继续往下扫描; 然而name字段添加唯一索引了,加不加limit 1,意义都不大。
20 1000w条数据,使用limit offset分页时,为什么越往后返越慢?如何解决?
例如:
limit 100000,20; # 从第十万开始往后取二十条,
limit 20 offset 100000; # limit 后面是取20条数据,offset后面是从10w条数据开始读
因为当一个数据表过于庞大,LIMIT offset,length中的offset值过大,则SQL查询语句会非常缓慢
- 优化一:先看主键,再分页:
select * from tb where id in (select id from tb where limit 10 offset 30)
- 优化二: 记录当前页,数据、ID、最大值和最小值(用于where查询) 在翻页时,根据条件进行筛选,筛选完毕后,再根据limit offset 查询
select * from (select * from tb where id > 2222) as B limit 10 offset 0;
- 优化三: 可以按照当前业务需求,看是否可以设置只允许看前200页; 一般情况下,没人会咔咔看个几十上百页的。
21 悲观锁和乐观锁
21.1 悲观锁和乐观锁的区别?
- 悲观锁
会从数据开始更改时就将数据锁住,直到更改完成才释放;
会造成数据库访问时间较长,并发性不好,特别是长事务。
传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。
- 乐观锁
直到修改完成,准备提交修改到数据库时才会锁住数据,完成更改后释放;
乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。
在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。
21.2 两种锁的使用场景
从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适。
21.3 乐观锁常见的两种实现方式
版本号机制
一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。
CAS算法
即compare and swap(比较与交换),是一种有名的无锁算法。无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。CAS算法涉及到三个操作数
- 需要读写的内存值 V
- 进行比较的值 A
- 拟写入的新值 B
当且仅当 V 的值等于 A时,CAS通过原子方式用新值B来更新V的值,否则不会执行任何操作(比较和替换是一个原子操作)。一般情况下是一个自旋操作,即不断的重试。
21.4 乐观锁的缺点
-
ABA 问题
- ABA 问题是乐观锁一个常见的问题。如果一个变量V初次读取的时候是A值,并且在准备赋值的时候检查到它仍然是A值,那我们就能说明它的值没有被其他线程修改过了吗?很明显是不能的,因为在这段时间它的值可能被改为其他值,然后又改回A,那CAS操作就会误认为它从来没有被修改过。这个问题被称为CAS操作的 "ABA"问题。
- JDK 1.5 以后的 AtomicStampedReference 类就提供了此种能力,其中的 compareAndSet 方法就是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。
-
循环时间长开销大
自旋CAS(也就是不成功就一直循环执行直到成功)如果长时间不成功,会给CPU带来非常大的执行开销。 如果JVM能支持处理器提供的pause指令那么效率会有一定的提升,pause指令有两个作用,第一它可以延迟流水线执行指令(de-pipeline),使CPU不会消耗过多的执行资源,延迟的时间取决于具体实现的版本,在一些处理器上延迟时间是零。第二它可以避免在退出循环的时候因内存顺序冲突(memory order violation)而引起CPU流水线被清空(CPU pipeline flush),从而提高CPU的执行效率。
-
只能保证一个共享变量的原子操作
CAS 只对单个共享变量有效,当操作涉及跨多个共享变量时 CAS 无效。
但是从 JDK 1.5开始,提供了AtomicReference类来保证引用对象之间的原子性,你可以把多个变量放在一个对象里来进行 CAS 操作.所以我们可以使用锁或者利用AtomicReference类把多个共享变量合并成一个共享变量来操作。
22 锁机制与InnoDB锁算法
22.1 MyISAM和InnoDB存储引擎使用的锁:
- MyISAM 采用表级锁(table-level locking)。
- InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁
22.2 表级锁和行级锁对比:
- 表级锁:
Mysql中锁定 粒度最大 的一种锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。其锁定粒度最大,触发锁冲突的概率最高,并发度最低,MyISAM和 InnoDB引擎都支持表级锁。
- 行级锁:
Mysql中锁定 粒度最小 的一种锁,只针对当前操作的行进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。
22.3 InnoDB存储引擎的锁的算法有三种:
- Record lock:单个行记录上的锁
- Gap lock:间隙锁,锁定一个范围,不包括记录本身
- Next-key lock:record+gap 锁定一个范围,包含记录本身
- 相关知识点:
- innodb对于行的查询使用next-key lock
- Next-locking keying为了解决Phantom Problem幻读问题
- 当查询的索引含有唯一属性时,将next-key lock降级为record key
- Gap锁设计的目的是为了阻止多个事务将记录插入到同一范围内,而这会导致幻读问题的产生
- 有两种方式显式关闭gap锁:(除了外键约束和唯一性检查外,其余情况仅使用record lock)
A. 将事务隔离级别设置为RC B. 将参数innodb_locks_unsafe_for_binlog设置为1
23 drop、delete与truncate区别?
23.1 用法不同
- drop(丢弃数据): drop table 表名 ,直接将表都删除掉,在删除表的时候使用。
- truncate (清空数据) : truncate table 表名 ,只删除表中的数据,再插入数据的时候自增长id又从1开始,在清空表中数据的时候使用。
- delete(删除数据) : delete from 表名 where 列名=值,删除某一列的数据,如果不加 where 子句和truncate table 表名作用类似。
truncate 和不带 where 子句的 delete、以及 drop 都会删除表内的数据,但是 truncate 和 delete 只删除数据不删除表的结构(定义),执行drop语句,此表的结构也会删除,也就是执行 drop 之后对应的表不复存在。
23.2 属于不同的数据库语言
truncate和drop 属于DDL(数据定义语言)语句,操作立即生效,原数据不放到 rollback segment 中,不能回滚,操作不触发 trigger。而 delete 语句是DML (数据库操作语言)语句,这个操作会放到 rollback segement 中,事务提交之后才生效。
DML 语句和 DDL 语句区别:
- DML是数据库操作语言(Data Manipulation Language )的缩写,是指对数据库中表记录的操作,主要包括表记录的插入(insert)、更新(update)、删除(delete)和查询(select),是开发人员日常使用最频繁的操作。
- DDL是数据定义语言(Data Definition Language)的缩写,简单来说,就是对数据库内部的对象进行创建、删除、修改的操作语言。它和 DML 语言的最大区别是 DML 只是对表内部数据的操作,而不涉及到表的定义、结构的修改,更不会涉及到其他对象。DDL 语句更多的被数据库管理员(DBA)所使用,一般的开发人员很少使用。
23.3 执行速度不同
一般来说:drop>truncate>delete。
24 数据库设计通常分为哪几步?
- 需求分析 : 分析用户的需求,包括数据、功能和性能需求。
- 概念结构设计 : 主要采用E-R模型进行设计,包括画E-R图。
- 逻辑结构设计 : 通过将E-R图转换成表,实现从E-R模型到关系模型的转换。
- 物理结构设计 : 主要是为所设计的数据库选择合适的存储结构和存取路径。
- 数据库实施 : 包括编程、测试和试运行
- 数据库的运行和维护 : 系统的运行与数据库的日常维护。
参考: