文章目录
- @[TOC](文章目录)
- 一、基本概念
- 二、事务的操作
- 1.设置全局事务隔离级别
- 2.设置事务提交方式
- 3.事务操作
- 三、事务隔离性
- 1.隔离性概念
- 2 .隔离级别设置
- 四、MVCC多版本控制
- 2. read view
文章目录
- @[TOC](文章目录)
- 一、基本概念
- 二、事务的操作
- 1.设置全局事务隔离级别
- 2.设置事务提交方式
- 3.事务操作
- 三、事务隔离性
- 1.隔离性概念
- 2 .隔离级别设置
- 四、MVCC多版本控制
- 2. read view
一、基本概念
事务是由若干条具有逻辑相关性的SQL语句组成的,用来完成某种任务的**逻辑单元.**事务具有原子性,一致性,隔离性,持久性4大属性.
原子性:保证事务要么不执行,要么执行完,如果发生错误就回滚到事务发生前的状态,就跟事务没有发生一样.
一致性:保证事务执行前和执行后,数据库的完整性不会被破坏.其他事务看到的数据库是一致的,不会看到事务执行过程中的不确定的数据,一致性是由原子性保证的,与用户逻辑强相关,由用户决定,如果因为用户逻辑导致事务中有的SQL语句没有成功执行,就会造成数据库的不一致.
隔离性:事务操作的数据对于其他事务是隔离的.不会影响其他事务,也不会被其他事务影响.
持久性:事务的结果在数据库中永久有效,不会因为数据库故障被破坏.
事务存在的意义是为了方便上层应用程序的使用,有了事务,应用程序层面就不需要关系,数据库操作失败应该怎么做,并发访问数据库应该怎么做,只需要关心怎么操作数据库,操作过程中的各种问题不需要关心.简化了应用程序的编程模型.
不同的存储引擎支持事务的情况不同.MySQL只有innodb支持事务.myisam不支持事务.show engines\G可以查看存储引擎属性信息.
事务的提交方式有自动提交和手动提交两种,show variables like ‘autocommit’;语句可以查看事务提交方式ON为自动提交,OFF为手动提交set autocommit=1设置自动提交,set autocommit=0设置手动提交
二、事务的操作
1.设置全局事务隔离级别
set global transation isolation level read uncommitted 设置事务隔离级别,设置完毕需要重启终端.
select @@tx_isolation;查看事务隔离级别
2.设置事务提交方式
autocommit=0为非自动提交,1为自动提交方式
3.事务操作
手动启动事务begin或者start transaction
事务回滚savepoint 变量名,设置保存点,rollback,回滚.回滚操作可以全部回滚,也可以回滚到保存点,回滚到保存点,保存点之后的数据全部清除,保留之前的数据.
提交事务commit,提交之后事务就无法再回滚了,如果SQL发生异常程序退出时,SQL会自动回滚到事务开始的时候,与是否自动提交无关.
单个SQL语句也构成事务,当设置自动提交时,每条SQL语句执行完会自动提交,反之需要commit手动提交.
三、事务隔离性
1.隔离性概念
因为事务并发执行需要保持事务的原子性,保证多事务并发时不互相干扰,所以有了隔离性,因为允许事务执行时更具情况,可以收到不同程度的干扰,所有有了隔离级别.
事务隔离级别有4中,读未提交,读提交,可重复读,串行化.
脏读:一个用户事务中读到的数据是其他用户事务未提交的事务,这叫做脏读.
不可重复读, 两个事务并发执行,一个事务执行期间操作的数据因为另一个事务的提交发生了改变,导致结果出现差错叫做不可重复读.
**幻读:**在可重复读的隔离级别下,仍然可以读到新插入并且已提交的数据.
串行化:是事务级别的串行,对每个读的数据行加共享锁,插入,删除,修改都是串行的.
2 .隔离级别设置
设置全局隔离级别,会影响所有终端的隔离级别.
设置会话隔离级别,默认与全局隔离级别一致
查看隔离级别
四、MVCC多版本控制
概念: MVCC是用来解决读写冲突的无锁并发控制.
事务结构: 每个事务都由数据,事务id,隐式主键id,flag标志,回滚指针组成.MySQL内部还维护了一个缓冲区undo log.
flag: 使用delete删除数据不是真的删除数据,而是将数据flag设置为删除,这是出于数据恢复,删除需要移动数据等多方面考虑.
回滚操作: undo log 中存储了与实际写入操作相反的操作,回滚时,执行想反操作即可,例如实际执行insert语句,会在undo log中记录delete语句.
版本链: 每执行一条更新操作,会在undo log中记录数据项的历史版本,然后将历史版本数据项在undo log中的地址记录在已经更新的数据项的回滚指针表项中.多个历史版本就形成版本链,一个版本也叫一个快照,读历史版本也叫快照读.事务提交了,与事务相关,但是与其他
**读写操作并发执行: ** 使用读未提交隔离级别,双方都是当前读(读到的是最新的数据).如果是读提交,一个事务是当前读,一个是快照读.因为读的不是一个数据所以不用加锁,从根本上解决了幻读和脏读和不可重复读的问题.
2. read view
**概念: ** read view是事务进程快照读时创建的一个用于快照可见性判断的类,重要组成成员属性有m_low_limit_id,m_up_limit_id,m_create_trx_id,m_ids;
**m_low_limit_id: ** 高水位,表示与当前事务同时运行事务的id中最大一个事务id加1;
**m_up_limit_id: ** 低水位,表示与当前事务同时运行事务的id中最小的一个事务id;
**m_create_trx_id: ** 当前事务的id;
**m_ids: ** 与当前事务同时在运行的所有事务id;
**检查规则: ** 快照读时会用readview类中的数据对比版本链中数据,如果快照id小于低水位,说明是当前事务运行前就已经提交的数据,或者是id等于m_create_trx_id说明是当前事务的快照,应该看见.如果快照id大于等于高水位,说明该事务是在当前事务运行之后才出现的,不应该被看见.如果m_ids是空说明就当前一个事务在运行,那么所有快照都能被看见.如果快照id在m_ids中说明事务仍在活跃,不应该被看见,如果不在m_ids中说明事务已提交,可以被看见.
可重复读原理: 当事务进行快照读的时候,会创建一个readview对象,一直到当前事务结束都是用一个readview,此时与当前事务同时运行的事务的操作对于当前事务而言是不可见的,就算其他事务在当前事务执行期间结束,readview中仍然会哪些事务当做正在运行的事务,也是不可见的.
**读提交: ** 当前事务每次快照读都会创建新的readview,与当前事务同时运行的其他事务在没有提交前事务id是记录在m_ids中的,提交后当前事务再次快照读将重新创建readview,已经结束的事务id就不会出现在readview中,那么该事务的快照是可见的,就形成了读提交.