简介: 事务隔离知多少
内容
一 基础知识
1 事务特性 ACID
A 原子性 C 一致性 I 隔离性 D 持久性
2 并行事务出现的问题
1 脏读 读取了其他事务未提交的数据
2 不可重复性读 1 在同一个事务内多次查询的结果不一致 2 可以通过for update or RR模式的MVCC避免这种现象 3 针对的是update/delete操作
3 幻读 1 当前事务读第一次取到的数据比后来读取到数据条目少 通过 next key lock避免
这里要注意
官方文档实际要表达的意义是“在同一个事务内,多次连续查询的结果是一样的,不会因其他事务的修改而导致不同的查询结果”
当前事务如果未发生更新操作(增删改),快照版本会保持不变,多次查询读取的副本是同一个;当前事务如果发生更新(增删改),再次查询时,会刷新快照版本
3 mysql隔离级别
RU 读未提交 -> 其他事务可以读取未提交的事务
RC 读已提交 -> 其他事务只能读取已提交的事务 可以避免(脏读) 不可避免(不可重复性读和幻读) 锁(record lock)
RR 可重复性读-> 本事务在事务内多次读取的事务是一致的,不会产生变化,直到本事务提交 可以避免(脏读,不可复重复性读和幻读) 锁(record lock+gap lock)
SE 串行化->事务之前是串行化执行的,包括select
4 默认隔离级别
mysql rr级别 oracle rc级别
oracle应用迁移到mysql的时候要注意
金融级别的建议使用RR
5 可重复性读和读已提交的区别
1 可重复性读是在事务开始的时候只创建一次视图函数 直到事务结束 效果等同于(start transaction with consistent snapshot) 查询事务开启前提交的数据
2 读已提交是在每次执行的时候都创建一次视图函数 直到事务结束 查询在事务内语句前提交的数据
6 RR模式下的更新问题
问题描述 在RR模式下 select搜索的是旧库的快照,但是update更新的是新库的数据,导致更新问题
问题解决 在读取的过程中设置一个排他锁,在 begin 事务里, select 语句中增加 for update 后缀,这样可以保证别的事务在此事务完成commit前无法操作记录
7 快照的实现
1 事务开始时会向mysql申请一个transation id
2 事务中每行的变更被称为一个版本
3 每个版本都会导致trx_id(赋值为row_id)递增,作为标记版本
4 而数据版本的可见性规则,就是基于数据的 row trx_id...
5 快照是基于库做的
8 id自增长知多少
1 thread_id
内容 show processlist的第一列就是thread_id,用来进行标注
2 trx_id
内容 用来维护一致性读场景
3 xid
内容 用来维护二次提交的事务一致性(redo and binlog必须xid一致)
9 在生产环境中究竟是用RR还是RC模式
这取决与你的业务查询,因为RR和RC模式的根本区别在于采用select获取结果的不同可能性,如果你的业务依赖于大量的一致性读,就不该采用RC模式,如果只是少量的一致性读,则可以采用rc模式,一致性读用for update实现