事务的特性

  • 原子性:原子性是指单个事务本身涉及到的数据库操作,要么全部成功,要么全部失败。
  • 隔离性:隔离性侧重于多个事务之间的特性,也就是说多个事务之间是没有相互影响的,比如A给B转账;和B给C转账这两个事务是没有影响的
  • 一致性:一致性指事务执行前后的状态要一直,简单的例子还是转账,原来AB账户的钱加一起是100,相互转账完成时候彼此还是100(抛出别人给其转账的事务发生),所以一致性,理解起来就是事务执行前后的数据状态是稳定的,对于转账就是金额稳定不变,对于其他的事务操作就是事务执行完成之后,数据库的状态是正确的,没有脏数据。
  • 持久性:持久性是数据库一旦完成事务的提交之后,那么这个事务的状态就会持久在数据库中,而不用担心数据库 自身是否存在问题,只要事务完成提交,那么这个事务的操作都会影响数据库最终的状态。

    事务的锁

  • 根据读写,分为共享锁S和排它锁X
    共享锁:即读加锁,不能写并且可并行读
    排它锁:写加锁,其他读写都阻塞

  • 根据加锁范围分为表锁、行锁、间隙锁
    表锁:锁整个表,性能开销最大,其他的读写都要挂起
    行锁:锁整个行,以默认隔离级别为例:如果是读,那么会上共享锁,不允许写,如果是写,那么改行其他事务无论读写都得阻塞
    间隙锁:间隙锁分为两种,一种是不包含记录间隙锁(GAP),一种是包含记录间隙锁(Next-Key Lock: Gap Lock+Record Lock)间隙锁详细解释

    • 加锁的基本单位是(next-key lock),他是前开后闭原则
    • 插叙过程中访问的对象会增加锁
    • 索引上的等值查询—给唯一索引加锁的时候,next-key lock升级为行锁
    • 索引上的等值查询—向右遍历时最后一个值不满足查询需求时,next-key lock 退化为间隙锁
    • 唯一索引上的范围查询会访问到不满足条件的第一个值为止

      事务隔离级别

  • RAED UNCOMMITED:读未提交,任何操作都不加锁,所以能读到其他事务修改但未提交的数据行,也称之为脏读(Dirty Read);不使用一致性读视图

  • READ COMMITED:读操作不加锁,写操作加锁。读被加锁的数据时,读事务每次都读undo log中的最近版本,因此可能对同一数据读到不同的版本(不可重复读),但能保证每次都读到最新的数据(事务提交之后的,不可重复读,两次读不一致),但是不会在记录之间加间隙锁,所以允许新的记录插入到被锁定记录的附近,所以再多次使用查询语句时,可能得到不同的结果(Non-Repeatable Read);每条SQL执行前会重新计算一个一致性读视图
  • REPEATABLE READ:第一次读数据的时候就将数据加行锁(共享锁),使其他事务不能修改当前数据,即可实现可重复读。但是不能锁住insert进来的新的数据,当前事务读取或者修改的同时,另一个事务还是可以insert提交,造成幻读;在执行第一条SQL创建一致性读视图
    (mysql的可重复读的隔离级别解决了 “不可重复读” 和 “幻读” 2个问题,因为使用了间隙锁)
  • SERIALIZABLE:InnoDB 锁表,读锁和写锁阻塞,强制事务串行执行,解决了幻读的问题;

    MVCC

    搞清楚了各个隔离级别 下的锁的使用情况,那么在默认的隔离级别下,innoDB如何实现事务的隔离性并保证其高效的并发性呢,那么就应该谈一谈MVCC多版本控制,基于此有必要了解一下多版本控制的概念。

  • 一致性读视图ReadView:ReadView所解决的问题是使用READ COMMITTED和REPEATABLE READ隔离级别的事务中,不能读到未提交的记录,这需要判断一下版本链中的哪个版本是当前事务可见的。

ReadView中主要包含4个比较重要的内容:ReadView详细解释

  • m_ids:表示在生成ReadView时当前系统中活跃的读写事务的事务id列表。
  • min_trx_id:表示在生成ReadView时当前系统中活跃的读写事务中最小的事务id,也就是m_ids中的最小值。
  • max_trx_id:表示生成ReadView时系统中应该分配给下一个事务的id值。
  • creator_trx_id:表示生成该ReadView的事务的事务id。
    • MVCC:多版本并发控制(MVCC,Multiversion Currency Control)。一般情况下,事务性储存引擎不是只使用表锁,行加锁的处理数据,而是结合了MVCC机制,以处理更多的并发问题。Mvcc处理高并发能力最强,这种方式系统开销 比最大(较表锁、行级锁),这是最求高并发付出的代价。
    • innodb存储的最基本row中包含一些额外的存储信息 DATA_TRX_ID,DATA_ROLL_PTR,DB_ROW_ID,DELETE BIT

事务 - 图1

  • 6字节的DATA_TRX_ID 标记了最新更新这条行记录的transaction id,每处理一个事务,其值自动+1
  • 7字节的DATA_ROLL_PTR 指向当前记录项的rollback segment的undo log记录,找之前版本的数据就是通过这个指针
  • 6字节的DB_ROW_ID,当由innodb自动产生聚集索引时,聚集索引包括这个DB_ROW_ID的值,否则聚集索引中不包括这个值.,这个用于索引当中
  • DELETE BIT位用于标识该记录是否被删除,这里的不是真正的删除数据,而是标志出来的删除。真正意义的删除是在commit的时候