mysql怎么优化面试 mysql性能优化面试( 四 )


B+tree的查询效率更加稳定:由于内部结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引,所以,任何关键字的查找必须走一条从根结点到叶子结点的路 。所有关键字查询的路径长度相同 , 导致每一个数据的查询效率相当;
视图是一种虚拟的表,通常是有一个表或者多个表的行或列的子集 , 具有和物理表相同的功能 游标是对查询出来的结果集作为一个单元来有效的处理 。一般不使用游标 , 但是需要逐条处理数据的时候,游标显得十分重要 。
而在 MySQL 中,恢复机制是通过回滚日志(undo log)实现的,所有事务进行的修改都会先记录到这个回滚日志中 , 然后在对数据库中的对应行进行写入 。当事务已经被提交之后,就无法再次回滚了 。
回滚日志作用:1)能够在发生错误或者用户执行 ROLLBACK 时提供回滚相关的信息 2) 在整个系统发生崩溃、数据库进程直接被杀死后,当用户再次启动数据库进程时,还能够立刻通过查询回滚日志将之前未完成的事务进行回滚,这也就需要回滚日志必须先于数据持久化到磁盘上,是我们需要先写日志后写数据库的主要原因 。
InnoDB
MyISAM
总结
数据库并发会带来脏读、幻读、丢弃更改、不可重复读这四个常见问题,其中:
脏读:在第一个修改事务和读取事务进行的时候,读取事务读到的数据为100,这是修改之后的数据 , 但是之后该事务满足一致性等特性而做了回滚操作,那么读取事务得到的结果就是脏数据了 。
幻读:一般是T1在某个范围内进行修改操作(增加或者删除),而T2读取该范围导致读到的数据是修改之间的了,强调范围 。
丢弃修改:两个写事务T1 T2同时对A=0进行递增操作,结果T2覆盖T1,导致最终结果是1 而不是2 , 事务被覆盖
不可重复读:T2 读取一个数据 , 然后T1 对该数据做了修改 。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同 。
第一个事务首先读取var变量为50,接着准备更新为100的时,并未提交,第二个事务已经读取var为100,此时第一个事务做了回滚 。最终第二个事务读取的var和数据库的var不一样 。
T1 读取某个范围的数据,T2 在这个范围内插入新的数据,T1 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同 。
T1 和 T2 两个事务都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改 。例如:事务1读取某表中的数据A=50,事务2也读取A=50,事务1修改A=A+50,事务2也修改A=A+50 , 最终结果A=100,事务1的修改被丢失 。
T2 读取一个数据,T1 对该数据做了修改 。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同 。
悲观锁,先获取锁,再进行业务操作,一般就是利用类似 SELECT … FOR UPDATE 这样的语句,对数据加锁,避免其他事务意外修改数据 。当数据库执行SELECT … FOR UPDATE时会获取被select中的数据行的行锁,select for update获取的行锁会在当前事务结束时自动释放,因此必须在事务中使用 。
乐观锁,先进行业务操作 , 只在最后实际更新数据时进行检查数据是否被更新过 。Java 并发包中的 AtomicFieldUpdater 类似,也是利用 CAS 机制,并不会对数据加锁,而是通过对比数据的时间戳或者版本号,来实现乐观锁需要的版本判断 。
分库与分表的目的在于,减小数据库的单库单表负担 , 提高查询性能 , 缩短查询时间 。
通过分表,可以减少数据库的单表负担,将压力分散到不同的表上,同时因为不同的表上的数据量少了,起到提高查询性能,缩短查询时间的作用 , 此外,可以很大的缓解表锁的问题 。分表策略可以归纳为垂直拆分和水平拆分:

推荐阅读