数据库

[toc]

索引

索引优化是对查询性能优化的最有效手段。是存储引擎能够快速定位记录的秘密武器。

索引的数据结构

InnoDB存储引擎大多情况下使用B+树建立索引,这是关系型数据库中查找最为常用和有效的索引,但是B+树索引并不能找到一个给定键对应的具体值,它只能找到数据对应的页,数据库把整个页读入到内存中,并在内存中查找具体的数据行。
B+树是平衡树,查找任意节点消耗的时间相同,因此比较次数就是B+树的高度。

聚集索引和辅助索引

数据库中的B+树索引可以分为聚集索引(clustered index)和辅助索引(secondary index)。聚集索引存放一条记录的全部信息,辅助索引只包含索引列和一个用于查找对应行记录的书签。
聚集索引:正常的表应该有且仅有一个聚集索引(绝大多数情况下是主键),表中的所有记录数据都是按照聚集索引的顺序存放的。
辅助索引:叶节点不包含行记录的全部数据,仅包含索引中的所有键和一个用于查找对应行记录的书签,辅助索引只用于加速数据的查找。

锁的出现是为了处理并发问题,数据库是一个多用户的资源,当出现并发的时候就会出现例如读“脏”数据,修改丢失等问题。数据库并发需要使用事务控制,事务并发又需要锁来控制。

乐观锁和悲观锁

乐观锁和悲观锁都是并发控制的机制,在原理上有本质区别
乐观锁:是一种思想,并不是一种真正的锁。读取数据时不担心被修改,在更新时判断是否被修改过,没被修改就更新,否则重试。
悲观锁:一种真正的锁。在获取资源前就对资源加锁,确保同一时刻只有有限的线程能够访问该资源,其他想获取的操作都会进入等待状态。
乐观锁适用于读操作较多的场景,不会存在死锁的问题,但是冲突频繁和重试成本高时还是推荐使用悲观锁。

共享锁和互斥锁

对数据的操作只有两种:读和写,针对这两种InnoDB实现了标准的行级锁。只对某一个数据加锁。
共享锁(读锁):允许事务对一条行数据进行读取。之间兼容
互斥锁(写锁):允许事务对一条行数据进行删除和更新。与其他任意锁都不兼容
思考WHY这么设计:因为我们可以对数据库并行读,串行写。这样不会发生线程竞争,实现线程安全。

意向锁

意向锁属于表级锁。对当前操作的整张表加锁。
意向共享锁:事务想在获得表中某些记录的共享锁,需要在表上先加意向共享锁
意向互斥锁:事务想在获得表中某些记录的互斥锁,需要在表上先加意向互斥锁。

锁的算法

锁是如何添加到对应的数据行上的。
Record Lock(记录锁):加到索引记录上的锁。
Gap Lock(间隙锁):对索引记录中的一段连续区域的锁。SELECT * FROM ... FOR UPDATE
Next-Key Lock:记录锁和间隙锁的结合,解决幻读的问题。

事务

事务四大特性

Automatic(原子性):一个事务要么完全发生,要么完全不发生
Consistency(一致性):事务把数据库一个一致状态变为另一个一致状态
Isolation(隔离性):在一个事务提交之前,其他事务察觉不到事务的影响
Durability(持久性):一旦事务提交,将是永久被保存的

事务四种隔离级别

  • Read Uncommitted (读未提交):查询时是不加锁,更新时加行级共享锁,可能读到未提交的行(Dirty Read)
  • Read Committed(读已提交):查询是只对记录加记录锁,不会在记录之间加间隙锁,所以允许新纪录插入到被锁定记录的附近。多次查询时可能得到不同结果(Non-Repeated Read)。
  • Repeated Read(可重复读):查询时加行级共享锁,多次读取同一范围的数据会返回第一次查询的快照,不会返回不同的数据行,可能会发生幻读
  • Serializable(串行化):读取时加表级共享锁,更新时加表级排它锁。

四种隔离级别下的问题

脏读:一个事务中,读取了其他事务未提交的数据
不可重复读:一个事务中,同一行记录被访问两次得到不同结果
幻读:在一个事务中,同一个范围内的记录被读取时,其他事务向这个范围添加了新的记录

你可能感兴趣的:(数据库)