数据库面试内容整理
数据库的三范式
- 第一范式(1st NF - 列都是不可再分)
第一范式的目标是确保每列的原子性 ,即没一列都是不可再分的最小单元数据 - 第二范式(2nd NF -每个表只描述一件事情)
首先必须满足第一范式,并且表中非主键列不存在对主键的部分依赖。第二范式要求每个表只描述一件事情 - 第三范式(3rd NF - 不存在对非主键列的传递依赖)
满足第二范式,并且表中的列不存在对非主键列的传递依赖
Mysql中有几种锁
InnoDB支持行锁和表锁,默认行锁。MyISAM支持表锁
表锁:开销小,加锁快,不会出现死锁。锁粒度大,发生锁冲突概率最高,并发度最低。
行锁:开销大,加锁慢,会出现死锁。锁粒度小,发生锁冲突概率小,并发度最高。
Mysql优化
优化数据类型
- 尽量避免NULL,NULL需要特殊处理,大多数使用NOT NULL,或者使用一个特殊的字符,如设置0,-1为默认值
- 尽可能的使用更小的字段,Mysql从磁盘中读取的数据存储到内存中,然后通过CPU的周期和I/O读取它,这就意味着越小的数据类型占用的数据中间越小
小心字符集转换
- 客户端或者应用程序使用的字符集可能跟表本身的字符集不同,这就需要Mysql在运行过程中隐含的进行转换,此外要确定字符集UTF-8是否支持多字节空间,因为他们需要更多的存储空间。
优化子查询
- 遇到子查询的时候,mysql的优化引擎并不是最有效的,这也就是为什么将子查询转换为连接查询的原因了,优化器已经能正确的处理连接查询了,当然要注意的一点是,确保第二个(连接的)表的连接列是由索引的,在第一个表上Mysql通常会对第二张表的查询子集进行一次全表扫描,这是嵌套循环算法的一部分。
优化UNION
- 在跨多个不同的数据库查询的时候,UNION是一个有趣的优化方法。UNION从两个不相关的表返回数据,这就意味着不会出现重复的行,同时也必须对数据进行排序,我们知道排序是非常消耗资源的,特别是对大表进行排序
- UNION ALL可以大大的加快速度,如果你知道你的数据不会重复,或者是不在乎重复的数据,这种时候使用UNION ALL更适合。此外,还可以在应用程序逻辑中采用某些方法避免重读的行,这样UNION ALL和UNION返回的结果都是一样的,只不过UNION ALL不会进行排序。
Truncate delete drop的区别
drop(DDL语句): 是不可逆操作,会将表所占用的空间全部释放
Truncate(DDL语句): 只针对删除表的操作,在删除过程中不会激活与表有关的删除触发器并不会把删除记录放在日志中;当表备Truncate后,这个表和索引会回复初始大小、
delete(DML语句):
可以删除表,也可以删除行,但是删除记录会被保存到日志中,而且表空间大小不会恢复原来。
执行速度:dorp>truncate>delete
sql函数
数字函数
- Abs(num)求绝对值
- floor(num)向下取值
- ceil(num)向上取值
字符串函数
- insert(s1index,length,s2)替换函数
s1表示被替换的字符串
s2表示将要替换的字符串
Index表示被替换的位置,从1开始
length表示替换的长度 - upper(str)将字母改为大写
- lower(str)将字母改为小写
- left(str,length)返回str字符串前length个字符
- right(str,length)返回str字符串后length个字符
- substing(str,index,length)返回字符串str从index位开始长度为length个字符
- reveser(str)将字符串倒序输出
日期函数
- curdate(),current_date()获取当前日期
- now()获取当前日期和时间
- datediff(d1,d2)计算d1和d2日期之间相隔时间
- adddate(date,num)返回从date之后num天的日期
- subdate(date,num)返回date日期之前num天的日期
聚合函数
- Count(字段)根据某个字段统计总记录数
- sum(字段)计算某个字段的数值总和
- avg(字段)计算某个字段的数值的平均值
- Max(字段)、Min(字段)计算某个字段的数值的最大、最小值
事务
什么是事务
事务是数据库操作的最小单位,是作为单个逻辑单元的执行的一系列操作。这些操作作为整体去提交,要么都执行,要么不执行
事务的四个特性
- 原子性
事务中的操作,要么全做完,要么全部做完 - 隔离性
同一时间,只允许一个事务操作数据 - 持久性
事务完成之后,事务对数据库的所有操作都保存到数据库中 - 一致性
事务操作前后,数据库的完整性没有遭到破坏,比如A给B转钱,A钱少了,而B钱没多
事务并发问题
首先先搞清楚脏读、不可重复读、幻读这些东西
- 脏读
读取到另外一个事务回滚前的数据,比如B用一百块钱去买东西,花了五十,而A读取到此时B还剩五十,但B由于事务回滚没有执行成功,而B还有一百。而A读取到的B还剩五十就是脏数据。 - 不可重复读
在不同时间,读取到的数据不同。比如B用一百块钱去买东西,此时A读取到B剩余一百,之后B买东西花掉五十,此时A由读取到B剩余五十。 - 幻读
两次读取到的对数据的计数不同,比如现查询有三个用户,但增加或者删除一个用户之后,查询出来的结果跟之前的不同。
-总结
不可重读侧重于修改数据所形成的的两次数据内容不同,而幻读侧重于增删。
事务隔离级别 | 脏读 | 不可重复读 | 幻读 | 数据库默认级别 |
---|---|---|---|---|
读未提交(read-uncommitted) | 是 | 是 | 是 | |
读已提交(read-committed) | 否 | 是 | 是 | Orcale、SqlServer |
可重复读 (repeatable-read) | 否 | 否 | 是 | Mysql |
串行化(serializable) | 否 | 否 | 否 |
Redis
什么是Redis
redis是一种免费开源的key-value内存数据库,通常被认为是一个数据结构服务器,主要是因为拥有丰富的数据结构
redis持久化
众所周知,redis是内存数据,把数据存储到内存中,读写效率增加,但如果Redis所在的服务器宕机,则数据将全部丢失,所以需要通过AOF和RDB将数据持久化到硬盘中。
- redis默认开启RDB(快照)持久化,在指定时间内执行,执行指定次数的写操作,将数据持久化到硬盘中
- RDB适合大规模的数据恢复,但它的数据一致性和完整性较差
- redis需要手动开启AOF持久化,AOF每秒钟读取写操作日志到AOF文件上
- AOF的完整性比RDB高,但由于内容多,数据的恢复效率较低
单点故障问题
用到redis的主从复制的功能,两台物理主机上分别都有运行着Redis-Server,其中一个Redis-Server是另一个的从库,采用双机热备技术,客户通过虚拟IP访问主机的物理IP,当主机宕机之后,切换到从机的物理IP。只是事后修复好主机之后,将之前的从机修改为主机(使用命令slave no one),主机变成其从机(slaveof ip PORT),这样才能保证修复器新增数据的一致性。