标签:数值 原因 幻读 rac name oba 做了 height 使用
1.事务(Transaction)定义:
是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。
2.事务的特性
3.数据库隔离级别设置
查看当前事务级别:
查询结果:
设置数据库事务管理级别,将其设置为读未提交:
set transaction isolation level Read uncommitted
set global transaction isolation level Read uncommitted
set session transaction isolation level Read uncommitted
注意:
如果选择global,意思是此语句将应用于之后的所有session,而当前已经存在的session不受影响。如果选择session,意思是此语句将应用于当前session内之后的所有事务。
如果什么都不写,意思是此语句将应用于当前session内的下一个还未开始的事务。
修改隔离级别:
可以看到数据库的状态已经改变:
重新连接一下数据库即可生效
4.事务并发控制
多个线程都开启事务操作数据库中的数据时,数据库系统要能进行隔离操作,以保证各个线程获取数据的准确性,在介绍数据库提供的各种隔离级别之前,我们先看看如果不考虑事务的隔离性,会发生的几种问题:
(1)脏读
脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。
当一个事务正在多次修改某个数据,而在这个事务中这多次的修改都还未提交,这时一个并发的事务来访问该数据,就会造成两个事务得到的数据不一致。例如:向A用户转账100元,对应SQL命令如下
update account set money=money+100 where name=’A’; (此时A查看账户余额)
当只执行完SQL时,A查看账户,发现确实钱已到账(此时即发生了脏读),而之后若该事务发生异常回滚,只要该事务不提交,那么当A以后再次查看账户时就会发现钱其实并没有转。
举个栗子
a.新建账户表如下:
注意:
查看该表的数据库引擎,若该引擎不位InnoDB引擎,需要将其修改为innoDB引擎。
修改语句为:ALTER TABLE account ENGINE = InnoDB;
b.创建java项目,使用jdbc链接数据库,代码如下:
在回滚处打一个断点,运行此代码
这时A查询数据库,查询到了没有提交的数据
但是当我们放开断点,执行回滚之后,数据恢复原状,若A再次查询数据库,会发现钱实际上没有到账。
(2)不可重复读
不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的结果,这是由于在查询间隔,被另一个事务修改并提交了。
例如事务T1在读取某一数据,而事务T2立马修改了这个数据并且提交事务给数据库,事务T1再次读取该数据就得到了不同的结果,发送了不可重复读。
不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。
举个栗子:
新写一个通过jdbc查询数据的方法如下:
当执行完第一次查询,我们通过断点拦住,然后执行另一端代码,修改数据库中的值
运行结果:
(3)虚读(幻读)
幻读是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。
幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。
代码同上,但是在第二次查询前,我们不是修改数据,而是插入数据,就可能造成幻读:
执行结果:
第二次读到的数据多了一条,这就是幻读。
总结:数据的更新操作会出现不可重复读,数据的增删会出现虚读(幻读)。
此外除了不配置事务的隔离性导致的以上事务问题,还有以下有关于事务的问题:
(4)第一类丢失更新
此种更新丢失是因为回滚的原因,所以也叫回滚丢失。此时两个事务同时更新count,两个事务都读取到100,事务一更新成功并提交,count=100+1=101,事务二出于某种原因更新失败了,然后回滚,事务二就把count还原为它一开始读到的100,此时事务一的更新就这样丢失了。
(5)第二类丢失更新
此种更新丢失是因为更新被其他事务给覆盖了,也可以叫覆盖丢失。举个例子,两个事务同时更新count,都读取100这个初始值,事务一先更新成功并提交,count=100+1=101,事务二后更新成功并提交,count=100+1=101,由于事务二count还是从100开始增加,事务一的更新就这样丢失了。
4.配置数据库事务隔离级别解决并发控制问题
我们可以看出,上面各种异常情况都是多个事务之间相互影响造成的,要解决这些问题,就需要将两个事务之间需要某种方式将他们从某种程度上分开,降低直至避免相互影响。
数据库有如下四种隔离级别:
以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别,当然级别高,执行效率就越低。像Serializable这样的级别,就是以锁表的方式(类似于Java多线程中的锁)使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。在MySQL数据库中默认的隔离级别为Repeatable read (可重复读)。
在MySQL数据库中,支持上面四种隔离级别,默认的为Repeatable read (可重复读);而在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。
总结:
级别\可解决异常 | 第一类丢失更新 | 脏读 | 不可重复读 | 第二类丢失更新 | 虚读/幻读 |
读未提交 | N | N | N | N | N |
读已提交 | Y | Y | N | N | N |
可重复读 | Y | Y | Y | Y | N |
串行化 | Y | Y | Y | Y | Y |
标签:数值 原因 幻读 rac name oba 做了 height 使用
原文地址:https://www.cnblogs.com/red-evil/p/10057164.html