事务的简单介绍
事务的ACID特性
A-原子性
事务一个原子操作单元,对于数据的修改,要么全部执行,要么全部执行
以下有两种情况需要分析?
事务提交了,如果此时Buffer Pool的脏页没有刷盘,如何保证修改的数据生效?
如果事务没有提交,但是Buffer Pool脏页刷盘了,如果保证不该存在的数据撤销?
以上问题,需要引入Undo和Redo的概念,每次写事务,都会修改BudfferPool,从而产生相应的Redo和Undo日志,再刷新到磁盘之前,这些日志信息都会先写入到日志文件中
C-一致性
事务一旦提交,它对数据库中的数据的改变应该是永久性的,后续的操作或者故障不应该对其有任何的影响,不会丢失
I-隔离性
一个事务的执行不应该被其他的事务干扰
InnoDB支持的隔离性有四种,隔离级别从低到高,读未提交,读提交,可重复读,可串行化
锁和多版本控制技术就是用于保障隔离性
D-持久性
事务开始之前和是事务结束之后,数据库的完整性限制未被破坏
脏读:一个事务读到了另一个事务修改但未提交的数据
不可重复读:一个事务中多次读取同一行记录不一致,后面读取的和前面读取的不一致
幻读:一个事务中多次按照相同的条件查询,结果不一致,后续查询的结果和前面查询的结果不同,多了或少了行记录
处理事务的相关方案:
第一种是排队,完全按照顺序执行所有事务的数据库操作,不需要加锁,也就是全局排队,效果就是某一时刻只能处理一个事务操作
第二种是排他锁,先进入的事务独占数据项,其他事务被阻塞,等待前面的事务释放锁
第三种是读写锁,细化锁的颗粒度,区分读操作和写操作,让读和读之间不加锁,即可以实现读和读的并行,但是读和写,写和读,写和写几种情况之间还是需要加排它锁的
第四种MVCC,实现了对读和读并行,读和写并行,写和读并行,但是为了保持一致性,写和写并行没法实现
MVCC实现原理
目前只能在读已经提交的和可重复读两种隔离级别下工作
在MVCC并发控制中,读操作可以分为两类:快照读和当前读
数据库的事务隔离级别越高,并发问题就越小,但是并发处理能力就越差,事务的隔离级别,针对的是InnoDB引擎,支持事务的功能
查询mysql数据库的事务隔离级别的命令
show variables like 'tx_isolation'
手动设置事务的隔离级别
设置隔离级别为读未提交 set tx_isolation='READ-UNCOMMITTED'
设置隔离级别为读已提交 set tx_isolation='READ-COMMITTED'
设置事务隔离级别为重复读 set tx_isolation='REPEATABLE-READ'
设置事务隔离级别为序列化 set tx_isoaltion='SERIALIZABLE'
分别对四种事务的隔离级别进行说明
读未提交 处理更新丢失的问题,但是会造成脏读,意思就是读取其他会话中未提交的但是已经修改的数据
读已提交 只能读取其他会话中已经提交的数据,解决了脏读问题
以上对事务的隔离级别,锁,,mvcc进行了简单说明,下面介绍使用说明,
事务的隔离级别底层是对锁和mvcc的一种封装,类似对于事务并发控制的整体解决方案,只是隐藏了底层细节
锁是事务并发控制的基础,事务隔离性使用锁实现,不同的操作使用不同的锁,解决不同的读写操作问题
对于用户来说,首先使用隔离级别处理问题,当隔离级别无法处理问题时,然后考虑使用锁
mysql的默认隔离:可重复读
mysql查询事务隔离级别 show variables like 'tx_isolation'
oracle的默认隔离级别:读已提交
构建一个session处于事务中
declare trans_id Varchar2(100); begin trans_id := dbms_transaction.local_transaction_id( TRUE ); end;
记得不要提交
SELECT s.sid, s.serial#,CASE BITAND(t.flag, POWER(2, 28)) WHEN 0 THEN 'READ COMMITTED' ELSE 'SERIALIZABLE' END AS isolation_level FROM v$transaction t JOIN v$session s ON t.addr = s.taddr AND s.sid = sys_context('USERENV', 'SID');
常规开发使用默认的隔离级别,高并发需求中引入悲观锁,乐观锁处理问题