导读
- 数据库基础理论
- 索引
- 事务、分布式事务
- 锁、分布式锁
- 分库分表
- 存储引擎
- 隔离级别以及如何实现隔离级别
- 常见优化方案及问题解决方案
数据库基础
-
DDL、DML、DCL分别指什么
DML(data manipulation language)
它们是SELECT、UPDATE、INSERT、DELETE,就象它的名字一样,这4条命令是用来对数据库里的数据进行操作的语言
DDL(data definition language)
DDL比DML要多,主要的命令有CREATE、ALTER、DROP等,DDL主要是用在定义或改变表(TABLE)的结构,数据类型,表之间的链接和约束等初始化工作上,他们大多在建立表时使用
DCL(Data Control Language)
是数据库控制功能。是用来设置或更改数据库用户或角色权限的语句,包括(grant,deny,revoke等)语句。在默认状态下,只有sysadmin,dbcreator,db_owner或db_securityadmin等人员才有权力执行DCL explain命令 -
数据库的三大范式,五大约束
- 三大范式
- 第一范式(1NF):数据表中的每一列(每个字段)必须是不可拆分的最小单元,也就是确保每一列的原子性;
- 第二范式(2NF):满足1NF后,要求表中的所有列,都必须依赖于主键,而不能有任何一列与主键没有关系,也就是说一个表只描述一件事情;
- 第三范式(3NF):必须先满足第二范式(2NF),要求:表中的每一列只与主键直接相关而不是间接相关,(表中的每一列只能依赖于主键);
- 五大约束
-
主键约束(Primary Key Constraint) 唯一性,非空性
-
唯一约束(Unique Constraint) 唯一性,可以空(但只能有一个)
-
检查约束(Check Constraint) 对该列数据的范围、格式的限制(如:年龄,性别等)
-
默认约束(Default Constraint)该列数据的默认值
-
外键约束(Foreign Key Constraint)需要建立两表间的关系并引用主表的列
为什么很多公司不允许使用外键?
外键相当于把数据一致性放到db层来做,为什么不建议放在数据层做,因为应用层机器更便宜,遇到性能瓶颈扩展的成本更低,而且对于互联网公司的应用,并发量大,需求迭代快速,变化也多,放在应用层做更加灵活。 -
- 三大范式
-
关系型数据库和非关系型数据库区别;
引擎
索引
事务
-
数据库事务ACID(原子性、一致性、隔离性、持久性)
-
原子性(A) 所谓的原子性就是说,在整个事务中的所有操作,要么全部完成,要么全部不做,没有中间状态。对于事务在执行中发生错误,所有的操作都会被回滚,整个事务就像从没被执行过一样。
-
一致性(C) 事务的执行必须保证系统的一致性,就拿转账为例,A有500元,B有300元,如果在一个事务里A成功转给B50元,那么不管并发多少,不管发生什么,只要事务执行成功了,那么最后A账户一定是450元,B账户一定是350元。
-
隔离性(I) 所谓的隔离性就是说,事务与事务之间不会互相影响,一个事务的中间状态不会被其他事务感知。
-
持久性(D) 所谓的持久性,就是说一单事务完成了,那么事务对数据所做的变更就完全保存在了数据库中,即使发生停电,系统宕机也是如此。
-
-
怎么实现ACID
- 原子性:依靠redo和undo日志实现
- 一致性:依靠隔离性来实现
- 隔离性:隔离级别(锁)和mvcc
- 持久性:SQL SERVER通过write-ahead transaction log来保证持久性。write-ahead transaction log的意思是,事务中对数据库的改变在写入到数据库之前,首先写入到事务日志中。而事务日志是按照顺序排号的(LSN)。当数据库崩溃或者服务器断点时,重启动SQL SERVER,SQLSERVER首先会检查日志顺序号,将本应对数据库做更改而未做的部分持久化到数据库,从而保证了持久性。
-
事务的隔离级别(读未提交、读已提交、可重复读、可序列化读)
- ru:可读未提交,会带来脏读
- rc:不可读未提交,出现了一次事务范围读出来两个不同的结果
- rr:在读的时候,不可修改,但是这种情况防不住查询,会产生幻读
- serializable:串行,序列化
-
隔离级别的实现原理
MySQL事务隔离级别的实现原理
深入理解mysql的事务隔离级别和底层实现原理
数据库事务系列-MySQL跨行事务模型
锁
-
悲观锁和乐观锁的原理和应用场景;
-
共享锁(S)和排他锁(X)
-
共享锁【S锁】 又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
-
排他锁【X锁】 又称写锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。
-
-
数据库的锁机制(行锁、表锁、间隙锁)
日志
-
一般情况下数据库宕机了如何进行恢复(什么是Write Ahead Log机制,什么是Double Write机制,什么是Check Point,redu、undo日志)
-
什么是redo和undo日志?
redu和undo简单介绍
redo和undo详解 -
binlog、undo日志和redo日志的区别?
-
什么是Write Ahead Log机制?
redo日志应首先持久化在磁盘上,然后事务的操作结果才写入db buffer,(此时,内存中的数据和data file对应的数据不同,我们认为内存中的数据是脏数据),db buffer再选择合适的时机将数据持久化到data file中。这种顺序可以保证在需要故障恢复时恢复最后的修改操作。先持久化日志的策略叫做Write Ahead Log,即预写日志。 -
什么是double write?
-
什么是Check Point?
checkpoint是为了定期将db buffer的内容刷新到data file。当遇到内存不足、db buffer已满等情况时,需要将db buffer中的内容/部分内容(特别是脏数据)转储到data file中。在转储时,会记录checkpoint发生的”时刻“。在故障回复时候,只需要redo/undo最近的一次checkpoint之后的操作。 -
MySQL中的MVCC机制是什么意思,根据具体场景,MVCC是否有问题;
Mvcc机制,线程会读取数据库的undo日志,每次都会读取最新的日志,这样做的有点是无需加锁就可以解决幻读的问题,但是缺点是,有可能读取到的不是最新值。
分库分表
-
说说分库与分表设计
- 随着业务量的上升,单表单库的模式已经不能满足要求。当一个表的数据量达到千万级别,就需要考虑分表了。
- 为什么达到千万级别,就需要考虑分表了,因为索引。每次插入数据,都需要重新计算索引。
- 分表只能解决对单表的查询插入速度,没法提高库的抗压能力。这时,可以进行垂直拆分,将一些功能比较独立聚合的模块拆分出来。
-
垂直拆分和水平拆分
- 垂直拆分 其实是分库,按照功能抽象,将不同模块的数据落在不同的库中
- 水平拆分 将一份数据,分到多个表中,每一个表是数据的一个分区
-
分库与分表带来的分布式困境与应对之策
-
表路由:分表的情况下,每次查询或者更新都要带上路由字段,增加了业务复杂度。
-
分布式事务:分库的情况下,原先一些多表关联查询现在变成了跨库查询。跨表的事务变成了分布式事务。
-
数据扩容:而且如果需要对系统进行进一步的扩容,将变得非常不方便,需要进行数据迁移。
-
表关联查询,可以少用表关联语句,通过程序进行组装。
-
-
拓展
mysql实战
-
limit 20000 加载很慢怎么解决
-
常见的数据库优化方案,在你的项目中数据库如何进行优化的
- 长事务和短事务
- 表的设计遵从三大范式
- 特别是行程模块的表,因为行程模块大对象比较多,要根据不同的业务类型横向分表,比如景点信息、行程段信息、吃住行、安全须知、行程报价等等。
-
MySQL并发情况下怎么解决(通过事务、隔离级别、锁)
-
死锁问题的解决
- 如果出现死锁,可以用SHOW INNODB STATUS命令来确定最后一个死锁产生的原因。返回结果中包括死锁相关事务的详细信息,如引发死锁的SQL语句,事务已经获得的锁,正在等待什么锁,以及被回滚的事务等。据此可以分析死锁产生的原因和改进措施
-
慢查SQL优化
-
自增主键用完了会怎么样?
扩展
spring事务
在Spring篇分析
分布式事务
在分布式篇分析