事务隔离
事务
事务是为了保证一组数据库操作,要么全部执行成功,要么全部执行不成功,InnoDB支持,Myisam不支持
事务的特性
- 原子性
- 一致性
- 隔离性
- 持久性
多事务同时执行引起的问题
- 脏读
- 不可重复读
- 幻读
事务隔离级别
- 读未提交(read uncommitted) 一个事务还没提交时,它做的变更就能被别的事务看到
- 读提交(read committed) 一个事务提交之后,它做的变更才会被其他事务看到
- 可重复读(repeatable read) 一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的
- 串行化(serializable) “写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突时,后访问的事务必须等前一个事务执行完成后,才能继续执行
配置事务方法
|
|
事务隔离的实现
每条记录在更新的时候都会同时记录一条回滚操作。通过回滚操作,都可以得到前一个状态的值
同一条记录在系统中可以存在多个版本,这就是数据库的多版本并发控制(MVCC)。
回滚日志在不需要的时候删除,当系统里没有比这个回滚日志更早的read-view时候,系统自动删除
尽量不要使用长事务
长事务意味着系统里面会存在很老的事务视图,在事务提交之前,回滚日志必须保留,这就会导致大量占用存储空间
事务的启动方式
显示启动事务
123begin transactiondo somethingcommit / rollbackset autocommit=0,将这个线程的自动提交关掉,只要你执行一个查询语句,事务就启动了,接下来的查询都在事务中,如果是长连接,将导致意外的长事务,这样直到你主动执行commit或者rollback语句或者断开连接才释放,可以通过set autocommit=1来显式方式来启动事务
12345begin tracsaction; # 不是一个事务的起点,在执行到它之后的第一个操作InnoDB语句,事务才真正启动start transaction with consistent snapshot; # 马上启动一个事务commit; # 提交事务autocommit=1;
事务隔离 or 不隔离
如果是可重复读隔离级别,事务启动时会创建一个视图read-view,之后事务执行期间,即使有其他事务修改了数据,该事务看到的仍然跟启动时看到的一样,也就是在可重复读隔离级别下执行事务,不受外界影响
Mysql中的两个“视图”:
- 一个view,用于查询语句定义的虚拟表,在调用的时候执行查询语句并生成结果
- InnoDB在实现MCVV时用到的一致性读视图,即consistent read view,用于支持RC(Read Committed,读提交)和RR(Repeatable Read,可重复读)隔离级别的实现,作用在事务执行期间用来定义”我能看到什么数据”
“快照”在MVCC里是怎么工作的
在可重复读隔离级别下,事务在启动的时候就拍下快照,这个快照是基于整库
Innodb里面每个事务有一个唯一的事务ID,叫作transaction id,它是在事务开始的时候向Innodb的事务系统申请的,是按申请顺序严格递增的
每行数据也都都是有多个版本的,每次事务更新数据时,都会生成一个新的数据版本,而且把transaction id赋值给这个数据版本的事务id,记为row trx_id; 同时,旧的数据版本要保留,并且在新的数据版本中能够有信息可以直接拿到它
数据表中一行记录,其实可能有多个版本(row),每个版本有自己的rowtrx_id
InnoDB利用了“所有数据都有多个版本”的特性,实现了“秒级创建快照的能力”
更新数据都要先读后写,而这个读,只能读当前的值,称之为”当前读”;当前读总是读取已经提交完成的最新版本
- 对于可重复读,查询只承认在事务启动前就已经提交完成的数据
- 对于读提交,查询只承认在语句启动前就已经提交完成的数据