MySql事务,索引,引擎

  1. 索引
    **二叉搜索树
    **B树
    **B+树:一棵矮胖树,元素有序,一个结点有多个元素,只有叶子结点存储数据,而非叶子结点存放索引而不存放数据

**索引遵循最左前缀匹配原则
**索引是帮助Mysql高效获取数据排好序的数据结构
**聚集索引:索引和数据放在一起,也叫聚簇索引,如Innodb
**非聚集索引:索引和数据不放在一起,也叫非聚簇索引,如myisam
**数据之间存在双向指针,在进行范围查找,如a>7就会先找a=7,完后将后面数据全部加载

**联合索引:create index 索引名 on 表名(列名,列名,列名);
–联合索引的冗余部分是联合索引,而叶子结点数据部分是主键索引,最终还是要回表查询,回表查询就是联合索引查询完主键索引,拿着主键索引在进行主键索引查询,查询了两次就是回表。
–联合索引必须遵循最左前缀原则,即索引的顺序是b,c,d,那么查询时必须按照顺序,如bcd,bc,b都可以,但是cd,c,d就不会走索引。
**联合索引进行范围查找不一定走索引,这些由优化器部分决定,因为联合索引的叶子结点保存的是主键索引,对于范围查找的所有结果都需要进行回表查询,效率非常低。但是回表次数很少时会走联合索引。

  1. 存储数据是以页的方式,一页大小为16KB,当进行查询时,先进行一次磁盘IO读入一页数据放入内存,然后进行查找,而磁盘IO非常的耗时,所以才以页的方式存储数据,以减少磁盘IO次数。

  2. Buffer Pool:从磁盘读入数据最小单位为页,当查询数据时,会先命中这一页然后复制到Buffer Pool,并且对数据进行缓存,后续查找更新就直接在该缓冲区进行。
    **该Buffer Pool中有一个数组,对拿到的页放入该数组,修改数据时也会先修改Buffer Pool中的数据,修改完成后,后台有线程会定时扫描然后持久化到磁盘,但是数组中页删除时机不同,无法连续,此时用链表进行统计空白页。对于更新过的页叫做脏页,脏页也会由一个链表统计,方便后台线程知道哪些页是脏页。
    **当Buffer Pool全部用满,再执行SQL语句,就要使用LRU算法(最近最少使用原则)淘汰部分页,来放入新的页。LRU算法实现也是使用链表,新加的页应该放在链表头,因为最近使用了。只要刚刚使用了就放在链表的前面,所以链表越前面就说明越经常访问。淘汰的时候直接删除链表最后的数据。
    **全表扫描可能会直接将整个Buffer Pool全部替换,清掉全部热点数据。所以LRU链表分为两个区域,热数据区域和冷数据区域,那么新的页会先放入冷数据区域头。但是这样的话,数据永远到不了热数据区域,如果冷数据区域的数据访问时间差大于1秒,会放入热数据区域,这里是大于一秒,因为对于全表扫描,两次访问相差时间很短,小于一秒,这种就不能放入热数据区域。
    **脏页的持久化,万一MySQL挂掉,而脏页还没来得及持久化,这里使用redo log解决。
    –当执行一条update,会先修改Buffer Pool中数据,生成脏页。然后update数据生成一个redo log,redo log进行持久化,显示修改成功,万一就在更新时挂掉了,那么下次重启,再读入更新失败数据的时候会读取redo log进行对比,这样获取的还是新数据。
    –只有事务在提交的时候才会执行持久化。
    –一页中保存很多行数据,在逻辑上连续,但是在磁盘上不连续,如果直接对脏页进行整页持久化,那么对这些随机地址的值更新就会发生很多次的随机IO。

  3. 引擎:
    **Innodb:支持事务,适合频繁修改以及涉及到安全性较高的应用,支持外键,MySQL5.5后默认的引擎就是Innodb,Innodb不保存表的行数,如select count() from table;会扫描全表计算有多少行。对于自增长的字段,Innodb必须包含只有该字段的索引。清空整张表,Innodb是一行一行的删除,效率比较慢。Innodb支持行锁。对于update table set a=1 where user like ‘%lee%’;操作会直接锁表。
    **myisam:不支持事务,而事务对于出错的增删操作可以进行回滚还原,所以myisam不能回滚还原错误的增删操作。myisam适合查询以及插入为主的应用。myisam不支持外键。myisam获取表的行数直接读出保存好的行数就好了,但是对于count()语句包含where时就需要全表扫描。myisam对于自增长字段,不强制包含只有该字段的索引,可以和其他字段建立联合索引。对于清空整个表,myisam直接重建表。

  4. MVCC:多版本并发控制
    **MVCC是用来解决读-写冲突的无锁并发控制,为每个修改保存一个版本。
    **好处:并发读写不用阻塞写操作,写操作也不用阻塞读操作,提高并发性能
    **同时能解决脏读,幻读,不可重复读问题
    **MVCC只适用于读已提交和可重复读隔离级别,如果是读未提交,存在脏读,即能读到未提交事务的数据行,如果是可序列化级别,那直接锁表了,也就不存在行版本问题了。
    **虽然MVCC是乐观锁的实现方式,即每行都有版本号,更新时对比版本号,但是MySQL写操作会加排它锁,而乐观锁又是消除锁定,二者相互矛盾,所以MySQL的MVCC只是实现了读的非阻塞。

  5. 并发事务带来的问题:
    **脏读:一个事务读取了另一个事务未提交的数据,那么读取到的数据就是错误的数据。
    **不可重复读:当多次读取同一条数据,但前后状态不一致,就叫做不可重复读,也会导致数据安全问题。
    **幻读:当一个事务对一个表属性修改后,如插入了一行,而另一个事务删除了一行,但是两次最终count和预期值就不符,这就是幻读,一般针对一列数据。

  6. 事务的特性:
    **隔离性:并发事务执行时要互不影响。
    **原子性:对一个事务的操作要么全部成功,要么全部失败。
    **持久性:事务执行完成后,结果要一直保存下来
    **一致性:事务执行前后,数据要保持一致

  7. 事务的隔离级别:
    **读未提交:不能解决任何问题
    **读已提交:可解决脏读问题
    **可重复读:可以解决脏读,不可重复读,但是不能解决幻读。也是mysql默认隔离级别
    **可序列化:可以解决任何问题,相当于锁表,但是性能开销很大

  8. 间隙锁:
    **如select * from table where a>10;那么就会对大于10的数据进行加锁,即便大于10的有些记录不存在,也会对这些间隙加锁。可以防止幻读问题

  9. 当前读:使用共享锁,排它锁这些操作都是当前读,读取的是数据的最新版本,读取时还要保证没有其他事务修改当前数据,会对读取数据加锁,也就是悲观锁的策略

  10. 快照读:像不加锁的非阻塞读就是快照读,快照读的前提就是隔离级别不是串行级别,串行级别就退化成当前读了。快照读就是基于MVCC,即多版本并发控制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值