原子性: 要么都执行,要么都不执行
隔离性: 所有操作全部执行完以前,其他会话看不到结果
一致性: 保证数据的状态操作前和操作后保持一致
持久性: 一个事务一旦提交,则数据将持久化到本地,除非其他事务对其进行修改
以MySQL的InnoDB引擎为例:
使用redo log(重做日志)保证事务的持久性,使用undo log(回滚日志)保证事务的原子性。使用锁机制、MVCC等手段保证事务的隔离性(默认的隔离级别是REPEATABLE-READ)。
保证了事务的持久性、原子性、隔离性后,一致性才能得到保障。
不可重复读与幻读的区别:
不可重复读重点是修改,多次读取同一条数据发现某些值被修改。
幻读重点是新增或删除,多次读取一条记录发现记录增多或减少。
注: 提升数据的隔离级别可以提升数据库的数据安全性,保证数据正确,但是由于数据库提升隔离性,是通过添加锁来实现,所以随之带来的是效率的降低,如果安全性很高,执行效率将会很低。数据库的执行效率和安全性都应该保证,所以应该在保证数据安全的情况下,尽可能的提升数据库的执行效率。
MVCC原理
MVCC示例
MVCC即多版本并发控制机制。主要用来实现读写的并发,并且不需要加锁,降低系统的开销。InnoDB存储引擎通过保存数据的某个时间的快照来实现,每行数据后面隐藏了两列,分别是创建版本号和删除版本号。
核心思想就是保存一个数据的多个版本号,使得当前读写不会产生冲突。
三种日志的详细实现可参考 JavaGuide 数据库部分
bin log 和 redo log的区别:
1)bin log会记录所有日志记录,包含InnoDB,MyISAM等存储引擎,而redo log只会记录InnoDB引擎的事务日志。
2)写入磁盘的时间不同,bin log只在事务提交完成后进行一次写入,而redo log在事务进行中不断的写入。
3)bin log是逻辑日志,记录的是SQL语句的原始逻辑;redo log是物理日志,记录的是在某个数据页上做了什么修改。
快照读情况下,InnoDB通过MVCC机制避免了幻读现象。而MVCC机制无法避免当前读情况下出现的幻读现象。因为当前读每次读取的都是最新数据,这时如果两次查询中间有其它事务插入数据,就会产生幻读。
如何避免幻读?
乐观锁和悲观锁只是一种思想,和数据库中的锁不同。
悲观锁: 对用户的修改持悲观的态度,认为每个用户都想修改数据,所以提前给数据上锁。
悲观锁的实现往往依靠数据库提供的锁机制。
悲观锁主要分为共享锁和排他锁
悲观锁适用于写操作较多的情况。
优点:为数据处理的安全提供了保证。
缺点:因为加锁,所以会让数据库产生额外的开销,降低了效率,还会增加了产生死锁的机会(两个事务相互想要修改对方锁住的数据,就产生了死锁),降低了并行性。
乐观锁: 对用户的修改持乐观的态度,认为用户有很小的概率修改数据,当用户对数据进行提交更新的时候,才会对数据进行检测。
乐观锁是先进行数据修改,然后判断是不是存在冲突,不存在就提交事务进行更新。
乐观锁的实现不依靠数据库,而是依靠数据本身
实现乐观锁可以通过CAS算法和通过版本号。CAS算法和通过版本号实现
乐观锁适用于写操作较多的情况下
优点:响应效率高,较好的实现了并行
缺点:如果冲突效率高,乐观锁重试会反复进行,时间效率很低。
参考资料
注: 行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了;两个事务不能锁同一个索引;insert,delete,update在事务中都会自动默认加上排它锁。
表锁: 表锁就是锁一整张表,表锁响应的是非索引字段,即全表扫描。(不会出现死锁,发生锁冲突几率高,并发低。)
间隙锁: 间隙锁是InnoDB引擎在可重复读提交下为了解决幻读问题引入的锁机制。间隙锁详解
支持三种不同的存储格式:静态表,动态表,压缩表
静态表:表中的字段都是固定长度的,优点是存储速度快,容易缓存,出现故障容易恢复。缺点是占用空间通常比动态表多(因为存储会按照列的宽度补足空格,取数据时会自动去掉空格)。
动态表:表中的字段不是固定长度,优点是占用空间少,缺点是频繁的更新,删除数据会更容易产生碎片。
压缩表:每个记录被单独压缩,所以访问开支小。
MySQL 5.5之前默认使用MyISAM存储引擎,MySQL 5.5之后默认使用InnoDB存储引擎。
MyISAM与InnoDB的区别:
二叉树、平衡二叉树,B树,B+树概念
二叉树: 树形结构,每棵树最多有2个节点,且左节点的值要小于根节点的值,右节点的值要大于根节点的值
平衡二叉树: 在二叉树的基础上增加了平衡的条件,即树的两边层级数不会大于1
B树: B树又称平衡多路查找树,B树每个节点最大会有M个节点,每个节点存储的是关键字(每个节点上的关键字是排序的)、关键字的指针、指向子节点的指针。
B+树: B+树是B树的升级版,除了叶子节点,每个节点保存的是关键字和指向子节点的指针,B+树中并没有除了叶子节点外其他节点并没有保存关键字指针,而叶子节点保存他所有父节点的关键字以及关键字指针。因为B+树没有保存关键字指针,所以他能保存的数据更多,能让树的高度更小,因此查询的效率更高。
B树和B+树的异同:
索引是一种用于快速查询和检索数据的数据结构。常见的索引结构有:B树,B+树和Hash。
优点:加快检索速度;创建唯一性索引,可以保证数据库表中的每一行数据的唯一性。
缺点:创建索引和维护索引耗费很多时间,当对数据进行CRUD时,还需要修改索引;索引需要使用物理文件存储,耗费空间。
注: 如果数据库的数据量不大,索引不一定能够带来很大提升。如果要对数据进行频繁的查询则可以建立索引,如果要对数据进行频繁的修改,则不建议建立索引。
索引的详解
索引的分类分为逻辑分类和物理分类。
逻辑分类
物理分类
聚簇索引的优点:
1)数据访问更快,因为聚簇索引将索引和数据保存在同一个B+树中,因此从局聚簇索引中获取数据比非聚簇快。
2)聚簇索引对于主键的排序和查找范围非常快。
缺点:
1)插入速度依赖于插入排序,按照主键的顺序插入是最快的方式,否则将会出现页分裂。因此,对于InnoDB表,经常定义一个自增的ID列作为主键。
2)更新主键的代价很高。
3)二级索引访问需要两次索引查找。
非聚簇索引的优点:
1)更新带价比聚簇索引要小,因为非聚簇索引叶子节点不存放数据。
缺点:
1)可能会二次查询(回表),当查询到索引对应的指针后,还需要根据指针或主键再到数据文件或表中查询。
2)依赖于有序数据。
索引查找的过程主要是产生磁盘I/O的消耗,主要靠磁盘IO次数,与磁盘存储原理有关。B+树除叶子节点外每个节点值保存键值,并不保存数据,所以每个节点保存的数据更多,所以树的高度更矮,所需要读取的磁盘IO次数更少。
局部性原理和磁盘预读
参考资料
最左前缀是用于联合索引,从左到右依次连续使用索引,即如果对三个字段建立联合索引,如果第二个字段没有使用索引,那么就不能跳过去使用第三个索引。
当使用组合索引时,不适应最左匹配原则的话会失效
当进行like模糊匹配时,以%开头(如:%abc)的无法使用索引,非%开头(如abc%)的可以,相当于范围查询
查询条件中列类型是字符串,没有使用引号,可能会因为类型不同发生隐式转换,使索引失效
查询条件中进行运算时
判断索引不等于某个值时
查询条件使用or时
第一范式: 第一范式是最基本的范式。每个字段值都要满足原子性,即不能再分割。
第二范式: 确保数据表中的每一列都与主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)
第三范式: 确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
分区: 把一个数据表的文件分成N个分区,这些区块可以在同一个磁盘上,也可以在不同的磁盘上。
优点:
1、存储更多数据。分区表的数据可以分布在不同的物理设备上,从而高效地利用多个硬件设备。和单个磁盘或者文件系统相比,可以存储更多数据
2、优化查询。在where语句中包含分区条件时,可以只扫描一个或多个分区表来提高查询效率;涉及sum和count语句时,也可以在多个分区上并行处理,最后汇总结果。
3、分区表更容易维护。例如:想批量删除大量数据可以清除整个分区。
缺点:
1、一个表最多只能有1024个分区2、MySQL5.1中,分区表达式必须是整数,或者返回整数的表达式。在MySQL5.5中提供了非整数表达式分区的支持。
3、如果分区字段中有主键或者唯一索引的列,那么有主键列和唯一索引列都必须包含进来。即:分区字段要么不包含主键或者索引列,要么包含全部主键和索引列。
4、分区表中无法使用外键约束
5、MySQL的分区适用于一个表的所有数据和索引,不能只对表数据分区而不对索引分区,也不能只对索引分区而不对表分区,也不能只对表的一部分数据分区。
分表: 把一个数据表分成N个小表。每个表对应三个文件:.MYD数据文件、.MYI索引文件、.frm表结构文件。
优点:
减少单张表的访问压力,减少数据库的负担,缩短查询时间
区别:
分区和分表的区别
1)实现方式上: 分表是真正的分表,每个小表都是一张完整的表,都对应三个文件。而分区之后还是一张表,只是存放数据的区块变多了,即几个区块,就有几个.MYD数据文件、.MYI文件,但是只有一个.frm表结构文件。
2)数据处理上: 分表后,数据是存放在分表里,总表只是一个外壳,存储数据发生在一个一个的分表里。分区只是把数据分成许多小块,分区后的表还是一张表,数据处理还得自己完成。
3)提高性能上: 分表后,单表的并发能力提高了,磁盘的I/O性能也提高了(总表根据不同的查询,将并发压力分到小表里)。分区后,突破磁盘I/O瓶颈,提高读写能力,增加性能。
4)实现的难易程度上: 分表如果通过merge分表,则难易程度跟分区差不多,其他的话实现很麻烦。分区的实现较为简单。
联系:
1)都能提高mysql的性能,在高并发状态下都能得到效率提升。
2)分区和分表不矛盾,可以相互配合,对于访问量大的且表数据较多的表,可以采用分区和分表结合(如果采用merge方式则不行),如果单单是数据量很大,则可以采用分区。
学习资料
基本思想: 首先为数据库连接创建一个“缓冲池”,并且预先在池中放入一定数量的数据库连接管道,当有客户端请求连接时,就从缓冲池中取出管道,并分配给客户端,当客户端使用完后,再将管道放回到连接池。如果所有管道已经被使用,那就再新建一些数据库连接管道放入缓冲池中(新建的数量与系统设置的参数相关)。客户端可以通过“缓冲池”提供的getConnection方法获取数据库的连接,使用完毕后再通过releaseConnection将连接返回。 注: 客户端返回连接后,连接并没有被关闭,而是被连接池管理器回收,未下一个连接者做好准备。这个过程避免了频繁的向数据库申请资源,释放资源带来的损耗。
优点:
红黑树与B+树的用途区别:
红黑树多用在内部排序,即全放在内存中,STL的map和set的内部实现就是红黑树。
B+树多用在外存上,B+树也成为一个磁盘友好的数据结构
为什么索引用B+树而不用红黑树?
我觉得还是因为红黑树的高度比较高,故IO次数较多,导致效率较低。