MySQL事务之隔离性

506 阅读4分钟
  以下内容是本人通过极客时间<MySQL实战45讲>记录的学习笔记  如有错误欢迎大家指出 共同进步
  
  注:转载注明出处

MySQL 的事务支持是在引擎层实现的 默认的MyISAM引擎不支持事务 后来出现了InnoDB引擎 我们都知道InnoDB 支持事务 接下来 以InnoDB为列子来探讨下事务的具体实现

事务特性

mysql事务的四大特性 ACID (原子性 一致性 隔离性 持久性) 今天我们主要来说说其中的隔离性

隔离性:当数据库上有多个事务同时执行的时候 为保证每个事务之间是独立的 互不干扰的
假设事务之间不是独立的 会出现什么问题 ?

1. 脏读(指为提交的数据)
    列-----》事务a更新一条记录 未commit之前。。。事务b读到了更新后的记录 那么事务b读到的就是脏数据。一旦事务a回滚 那么事务b读到的肯定是错误的脏数据  
2. 不可重复读(指读取数据本身的发现变化)
    列-----》在一个事务范围内 读取某些数据一段时间后再次读取 发现读取的数据已经发生的了改变
3. 幻读(指读取数据结果集的变化)
    列-----》一个事务按想用的检索条件 检索出来的结果集不同(其他事物的删除 新增) 

事务隔离级别

为了解决这些问题就出现了‘隔离级别’的概念 在这之前要明白 隔离的越彻底 效率就会越低 因此很多时候我们需要找一个平衡点。

SQL标准事务隔离级别包括

 读未提交:一个事务还没提交的时候,它的变更就能被别的事务看到。
 读提交:一个事务提交之后,它做的变更才能被其他的事务发现
 可重复读:一个事务在执行的过程中看到的数据(MySQL默认的隔离级别) 即使有别的事务对数据进行了更新操作 事务执行期间看到的数据必须是一致的
 串行化:对同一行记录 写会加写锁 读会加读锁 当出现读写锁冲突的时候 后访问的事务必须等前一个事务执行完成 才能执行
 
 
 总结:
 读未提交 事务a未提交 事务b也能读到
 读已提交 事务a提交之后事务b才能读到
 可重复读 事务a提交之后事务b也不去读
 串行     事务a没有提交 事务b不能进行任何操作

这4中隔离级别 并发性能依次降低 安全性依次提高

隔离级别的实现

事务实现 数据库里面会创建一个视图 访问的时候以视图的逻辑结果为准。

  可重复读:视图是在事务启动的时创建的 整个事务存在期间都用这个视图
  读已提交:这个视图是在每个SQL语句开始执行的时候创建的 但只作用于当前SQL
  读未提交:隔离级别下直接返回记录上的最新值 没有视图的概念
  串行化:  隔离级别下直接用加锁的方式来避免并行访问
  
  
  每次创建视图的时候 持久话当前的数据创建视图 后续直接从视图中读取

事务隔离的实现

MySQL中 每条记录在更新的时候都会同时记录一条回滚操作。记录上最新值 通过回滚操作 都可以回到前一个状态的值

假设一个值从1变成2 3 4 在回滚日志里有类似下面的记录

当前值是4 查询的时候 不同时刻启动的事务会有不同的read_view 视图A B C 里面,这一条记录值分别是1 ,2,4 同一条记录可以在系统中存多个版本 就是DB的多版本并发控制 mvcc 要想的到1 就得将当前值依次图中的所有操作回滚

同时 及时有另一个事务正在将4改为5 这个事务跟read_view A B C 对应的事务不会冲突

   什么时候删除记录:在不需要的时候删除 也就是说 系统判断 当没有事务再需要用到这些回滚日志的时候  当系统里比这个回滚日志更早的read_view的时候

长事务

需要花费很长时间的事务即长事务

长事务意味着系统会存很老的视图 由于这些事务随时可能访问数据库里面的任何数据 所以在这个事务提交之前 数据库里面可能用到的回滚记录都必须保留 这就会导致大量的存储空间

MySQL5.5之前 回滚日志和数据字典一起放到ibdata文件中的 即使事务提交 回滚段清理 文件也不会变小

除了影响回滚段 还会占用资源