#数据库三范式
第一范式:属性不可分
第二范式:非主属性完全依赖于键码(消除冗余)
第三范式:非主属性不传递依赖于其他键码
#如何理解ACID?
原子性(Atomicity)
事务被视为不可分割的最小单元
一致性(Consistency)
数据总是从一个一致的状态转移到另一个一致的状态(正确性)
隔离性(Isolation)
未提交的事务对其他事务不可见
持久性(Durability)
一旦数据提交则对应的修改将会永远保存在数据库中
ACID不是简单的平级关系,只有满足一致性,事务的执行结果才是正确的。无并发情况下,操作串行执行,只需要保证原子性,事务的一致性就能保证。并发情况下,需要同时保证隔离性和原子性才能保证事务的一致性。持久性是为了防止数据库崩溃导致数据不一致,所以可以说事务的最终的目的就是为了保证一致性。
#CHAR和VARCHAR的区别?
1.CHAR(10)的字宽是固定的,存储的字符小于10会在后面补空格,超过10则会截取。VARCHAR(10)允许存储小于等于10个字宽的内容,10只是限制最大字宽。
2.之所以说字宽而不是字节,主要是因为CHAR的存储方式跟字符集还有关系。比如ascii字符集下,CHAR(10)占用的空间为10个字节,而utf8字符集下占用的空间为10~30字节,且要求最少占用10个字节。VARCHAR占用的存储空间由存储内容决定,没有最少占用多少字节的限制。
3.CHAR在除LIKE之外的所有比较操作中都会移除尾部空格,而VARCHAR不会处理尾部空格。
#FLOAT和DOUBLE的区别?
FLOAT是单精度浮点数,占用4字节的空间,有效精度7位
DOUBLE是双精度浮点数,占用8字节的空间,有效精度16位
有效精度主要由尾数的位数决定,单精度尾数位为23位,双精度尾数位为52位。
#哪些情况可能导致数据库OOM?
1. 长连接长时间不释放
长连接长时间不释放可能导致OOM,现象就是MySQL异常重启。原因是MySQL执行过程中临时使用的内存在连接对象里面管理,这些资源在连接断开的时候才会释放。
2.长事务
长事务也可能导致OOM,典型场景如undo log数据页,事务提交后undo log页面不能立即删除,因为undo log还需要支持MVCC。事务提交后undo log会被放入链表中,后台purge线程会异步删除过期的undo log。事务开启式时会创建read view,而purge线程是根据read view创建时的trx_id来判断undo log是否过期的。如果有长事务存在的话,undo log占用的内存会越来越多,最终导致OOM。undo log数据的真正删除是通过把记录加入垃圾链表实现的,加入垃圾链表之后别的事务就访问不到这条记录了,可以复用该记录的空间。
#该不该使用查询缓存?
查询缓存弊大于利,有以下两点原因:
1.查询缓存使用KV结构,只要执行的SQL语句有一点不同,都没法儿用到缓存。
2.查询缓存涉及到的表只要有更新操作,相关的缓存都会失效。写多读少的数据库查询缓存的命中率会非常低,而且失效缓存操作需要加锁,可能会出现锁等待的情况。
#为什么COUNT(*)这么慢?
即使是同一个时刻的查询,因为MVCC的原因,InnoDB应该返回多少行也是不确定的。
其实InnoDB已经对COUNT(*)做了不少优化,因为统计聚簇索引返回的行数和统计二级索引返回的行数逻辑上是一样的,所以InnoDB会选择最小的那棵索引树来遍历。COUNT(*)、COUNT(主键)、COUNT(1)都表示返回满足条件的结果集的总行数,COUNT(字段)表示返回字段不为NULL的总行数。
统计全表数据量的时候MyISAM比InnoDB快,但是带条件统计数据量的时候就不见得了,MyISAM只缓存了全表数据量,带条件的统计也是需要计算的。