数据库隔离级别 ACID(原子性,一致性,隔离性,持久性),隔离得越严实,效率就会越低。mysql 默认隔离级别可重复读,在这一级别他已经解决了幻读的问题。

隔离性

  • 读未提交是指,一个事务还没提交时,它做的变更就能被别的事务看到。
  • 读提交是指,一个事务提交之后,它做的变更才会被其他事务看到。
  • 可重复读是指,一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。
  • 串行化,顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。

    事务隔离的实现

    mysql 默认事务隔离级别「可重复读」,在开启事务会有不同的read-view,同一条记录在系统中可以存在多个版本,就是数据库的多版本并发控制(MVCC)。MVCC 可以解决帮助 REPEATABLE-READ(可重复读)的幻读问题,因为他在开启事务的时候就生成视图(readView)

    一致性,ReadView

    在InnoDB引擎表中,它的聚簇索引记录中有两个必要的隐藏列:

  • trx_id这个id用来存储的每次对某条聚簇索引记录进行修改的时候的事务id。

  • roll_pointer每次对哪条聚簇索引记录有修改的时候,都会把老版本写入undo日- 志中。这个roll_pointer就是存了一个指针,它指向这条聚簇索引记录的上一个版本的位置,通过它来获得上一个版本的记录信息。

readview 在 undo 日志中,readview 结构:

结构 解释
m_ids 存放当前系统中活跃的事务集合
min_trx_id m_ids中最小的事务ID
max_trx_id 分配给下一个开启事务的事务ID
creator_trx_id 创建此ReadView的事务ID

事务ID:只有在对表中的记录做改动时(执行INSERT、DELETE、UPDATE这些语句时)才会为事务分配事务id,否则在一个只读事务中的事务id值都默认为0。

  • 判断trx_id 与 creator_trx_id是否相等,是则意味着此版本正在被当前事务操作,可以访问
  • 判断trx_id是否小于min_trx_id,表示此版本的生成事务已经提交,可以访问
  • 判断trx_id是否大于等于max_trx_id,表示此版本的生成事务已经提交,可以访问
  • 判断trx_id是否在m_ids中,若不在,则意味着此版本的创建事务已经提交,可以访问;若在,则表明此版本在创建ReadView时还在活动,不能访问。