常规数据库面试题1.事务的4大特性？
原子性，一致性，隔离性，持久性
2.事务的隔离等级
a. read uncommited :会出现脏读，重复读，幻读
b. read committed：会出现重复读和缓读
c. repeatable read：会出现缓读
d. serializable ：3个问题都解决
后面又多了一个快照的隔离级别：Snapshot Isolation
不考虑事务的隔离级别，会出现以下错误的情况
· 脏读：一个线程中的事务读到了另外一个线程中未提交update的数据。
· 重复读：一个线程中的事务读到了另外一个线程中已经提交的update的数据。
·虚读：一个线程中的事务读到了另外一个线程中已经提交的insert的数据。
对幻读的理解：对于查寻-插入的的场景，幻读的问题场景应该是查询不到，但是又插入不了（因为加了唯一索引）。这个不影响到业务。--不对
serializable通过加读锁的方式解决了幻读的问题，但是这样锁冲突的概率会比较高，一般不会用。
参考：图解mysql事务的四个隔离级别 - 墨天轮
MySQL中的幻读，你真的理解吗？ - 云+社区 - 腾讯云
关于幻读，可重复读的真实用例是什么？ - 知乎 这个理解更到位。使用多版本并发控制解决幻读问题。
oracle默认的隔离级别是repeatable read，一个线程在事务开始时，可以取到库中所有表的瞬时状态,读取到的数据是当前SCN(系统改变号)下的数据，在事务的过程中不会读取到其他线程对表的改变。
这样数据库存在一个高并发问题，一个i线程在先select得到A, 休眠10秒，再将A=A+1,写入到数据库中, 有另外一个线程j在i线程休眠期间，将数据库中的A值改成A+2。
那么数据库最终的结果就是，j线程对表的操作丢失。
在mysql中行锁需要由insert语句来触发，仅仅是事务开启和select操作是不能触发行锁的。
Oracle是否可以默认通过乐观锁的机制防止者中情况的发生呢，需要实验下。
select for update 操作的列 会加上读写锁。在加锁的线程执行commit操作之前，其它线程对加锁行的select for updae和写操作需要等待，但是如果只是普通的select是不会等待的。 但是对空记录是不能加锁的。
select for update 加锁的记录是事务之间立即可见的。
总结：数据库的事务机制，不能解决高并发下数据丢失的问题。这就是redis锁存在的意义。
3. 事务的传播属性
事务的传播属性分为7种：粗略的分可以分为3大类别：方法一定要在事务中进行，方法可以在也可以不在事务中进行，方法一定要在事务中进行。
默认是required，一定要在事务中进行，如果事务不存在，则需新建一个事务。
另外几种类型：
1. mandatory，必须在事务中进行，事务不存在则抛出异常
2. required_new, 启动一个新的事务执行方法，如果存在当前事务，则将当前事务挂起
3. supported，存在事务则在事务中进行，不存在事务则不再事务中进行
4. never，方法不能再事务中进行，如果存在事务则抛出异常
5. not_support, 不能在事务中进行，如果存在事务，则将事务挂起
6. nest，嵌套事务
4. 数据库3大范式
a.要有主键，可以shying雪花算法生成。
a. 列需要有原子性，字段不可以再分割：有时候也会违背，比如说值对象
c.表之间不要存在冗余信息，通过外键关联查询即可，最好还是不要违背，冗余信息维护起来很麻烦。如果查询一定需要，那就分两张表查吧。
5. 数据库索引的原理
参考博文：数据库索引原理 - konglingbin - 博客园
Mysql中的B+树：和B树对比，它在叶子节点之间加了双向列表，叶子节点的数据块之间可以相互访问，减少了索引时间和io时间（包括磁道寻址时间，旋转时间，传输时间，每次在10毫秒左右）。
Oracle中的B*树：与B+树的区别，非叶子节点间增加了双向链表相互连接
裂变的方式不一样：
B+树：当节点满时，创建一个新节点，将原节点中1/2的数据放到新节点
B*树：当节点满时，向考虑将数据放到兄弟节点中，如果说兄弟节点也满了，再考虑创建一个新节点，再将原节点1/3的数据放到新节点中。