什么是存储引擎?
存储引擎可理解为对磁盘的操作方式,是一套存储数据的规范,Mysql是一个插拔式的存储引擎。默认的Innodb并不是由Mysql团队研发,而是由第三方公司研发产生。它的最重要作用是修饰表,每个表也可以用不同的存储引擎来修饰。Innodb优秀的设计使得Mysql5.5之后的版本默认使用Innodb引擎
事务概述
隔离性:事务是一组不可分割的操作集合。破坏事务隔离性是由数据并发访问导致,破坏事务隔离性导致的脏读,幻读,不可重复读三个问题。使用四种事务隔离级别解决这些问题,具体机制是Mvcc机制与LBcc机制。
原子性:关注是语句的执行状态,当发生事务内部故障会破坏原子性,保证原子性的机制是,UNDO log反向扫描日志,撤销已做的更新操作
Mysql默认设置会话级别的自动提交,即执行一条语句会自动提交事务,无法做到原子性保证。故我们要将多条语句变成一个事务的话需要关闭自动提交,设置为手动提交。
一致性:并发访问的可见性设定,关注的是数据的一致,当发生系统故障如:系统断电,DBMS代码错误时,这些情况可能会导致未完成的事务对数据库的更新肯已经写入数据库,已经完成的事务对数据库的更新停留在缓冲区没来得及写入数据库。这都会破获一致性,解决方法是UNDO LOG+REDO LOG反向扫描日志撤销未完成的事务,正向扫描日志,找出故障发生前已经提交的事务进行重做
持久性:事务对数据库的改变应该是永久的,发生介质故障如磁盘损坏,会破坏持久性.解决方法是重装数据库(装入最新的数据库后备副本),然后REDO LOG+UNDO LOG
隔离级别
sql92 标准四种隔离级别:
Read Uncommitted 解决并发问题
Read Committed 解决脏读问题
Repeatable Read 解决不可重复读问题
Serializable 解决所有问题
Innodb默认的隔离级别是RR(Repeatable Read)级别,但是却解决了幻读问题,这便是Innodb的优秀之处
Innodb如何解决隔离性问题,即如何实现事务隔离级别?
1、利用锁的互斥性----->LBCC当前读 (悲观锁)
(Lock Based Concurrency Control)基于数据库当前版本的读写
如:update,delete ,insert,select * from table where id=1 lock in share mode(当前读)
2、多版本控制----->MVCC快照读(复制的多一份数据)(乐观锁)
(MultiVersion Concurrency Control)读取的是数据库历史版本,读取历史版本还有意义吗?其实快照读的历史版本是在数据修改时才生成的副本,并不是连续修改之前的版本,是一次修改之前的版本,即读取最新版本,也就保证了数据的正确性
如:select * from table where id=1(快照读)
Innodb的LBCC机制的具体实现
1、锁的分类
加排他锁(x):事务结束释放,不能加其他锁
delecte/update/insert默认
select * from where … for update
加共享锁(s):事务结束释放,可继续加共享锁,不能加排他锁
select * from where … lock in share mode
1、Innonb的行锁机制是在索引项上加锁实现,故若通过索引条件(where)进行检索,Innodb会锁住行,否则锁住整张表。
2、Innodb按照辅助索引(二级索引)进行检索时,辅助索引项和主键索引项都将被锁定,即是锁住行
2、行锁的具体实现
临键锁:
next-key(gap+lock):适用于范围查找,当在查询范围命中索引项时,会锁住当前索引项和索引项的下一个左开右闭区间。Innodb的默认行锁算法,巧妙解决幻读问题,而幻读产生原因是范围查找时其他线程在查找的范围内插入了数据,导致两次查找的范围结果不一样。使用临建锁之后,会锁住以关键字以及关键字的下一个区间,从而其他线程无法插入数据,解决幻读。
Innodb引擎默认推荐使用主键自增序列方式,也是为了解决幻读,因为插入数据,主键必然会自增长,此时增长的记录被锁住了,无法插入
间隙锁:
gap lock : 当记录不存在,会从临建锁退化成间隙锁,会锁住记录不存在的左开右开区间
记录锁:
record lock:当命中记录,退化成Record锁,锁住记录所在行