oracle 事务的管理

devtools/2024/9/24 20:37:49/

事务的特性
事务是由一组SQL语句组成的逻辑工作单元,这些语句要么全部执行,要么不执行,只要有一条SQL语句执行失败,则已执行的SQL语句会回滚到执行之前的状态,这样就保证了数据库数据的一致性,不产生混乱的数据信息。
通过事务,可以实现数据的共享,事务可以保证数据的一致性。只有COMMIT后,其他用户才可以看到数据更改。
事务处理的原理:
(1)在Oracle中,sql语句更改数据时,把旧值暂时写入一个叫回滚段(ROLLBACK SEGMENT)的空间中。
(2)COMMIT时,清除回滚段的旧值。
可撤消的语句: 适用于所有dml语句。
一组SQL语句操作要成为事务,数据库管理系统必须保证这组操作的原子性(Atomicity)、一致性(consistency、隔离性(Isolation)和持久性(Durability),这就是ACDI特性。
原子性是指事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败。比如在同一个事务中的SQL语句,要么全部执行成功,要么全部执行失败。
一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。举例说明:张三向李四转100元,转账前和转账后的数据是正确的状态,这就叫一致性,如果出现张三转出100元,李四账号没有增加100元这就出现了数据错误,就没有达到一致性。
隔离性:事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
持久性:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。例如在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当程序执行完成直到看到提示后,就可以认定事务正确提交,即使这时候数据库出现了问题,也必须要将事务完全执行完成,否则就会看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。

【例4-7】建立账号表account_money,在该表上建立约束,账户金额必须大于零。
写一段匿名块,从张三的账户1转账600元给账户2,查看转账是否成功。
具体代码如下:
–第四章\zsgc.sql

–建立账号表
create table account_money
(
id number(4) not null,
name varchar2(4) not null,
money number(5,2) not null
)
;
– 增加一个检查约束
alter table account_money
add constraint CK_money
check (money>=0);

–向张三账号增加数据
insert into ACCOUNT_MONEY (ID, NAME, MONEY)
values (1001, ‘张三’, 500.00);
insert into ACCOUNT_MONEY (ID, NAME, MONEY)
values (1002, ‘张三’, 1.00);

BEGIN
–从张三的1001账户转入张三的1002账户
UPDATE account_money a SET a.Money=a.Money-600 WHERE a.Id=‘1001’;
UPDATE account_money a SET a.Money=a.Money+600 WHERE a.Id=‘1002’;
COMMIT;–提交事务
EXCEPTION --异常处理
WHEN OTHERS THEN ROLLBACK;–出现异常就回滚
Dbms_Output.Put_Line(‘转账异常,转账失败’);
end;
Select * from account_money;

执行后,如图4-16所示。

图4-16查询表数据

在程序中提示转账失败,如图4-17所示。

图4-17转账失败

在上述代码中,因为账户设置了检查约束,当账户小于0时,就会出现异常。如果不进行事务异常处理,那么第二条更新语句会被执行。当做了事务异常处理后,当出现异常就会回滚。
【例4-8】写一个匿名块,查询出表account_money转账前的两个账户余额。然后从账户1001转账100元给账户1002,查询转账后的两个账户余额。如果转账失败,提示错信息并显示两个账户的余额。
具体代码如下:
–第四章\zsgc.sql

DECLARE
account_a account_money.Money%TYPE;
account_b account_money.Money%TYPE;
BEGIN
SELECT a.money INTO account_a FROM account_money a WHERE a.Id=‘1001’;
SELECT a.money INTO account_b FROM account_money a WHERE a.Id=‘1002’;
Dbms_Output.Put_Line(‘转账前A账户余额:’||account_a);
Dbms_Output.Put_Line(‘转账前B账户余额:’||account_b);
Dbms_Output.Put_Line(‘转账前总余额:’||(account_a+account_b));
UPDATE account_money SET money=money-100 WHERE ID=‘1001’;
UPDATE account_money SET money=money+100 WHERE ID=‘1002’;
COMMIT;
SELECT a.money INTO account_a FROM account_money a WHERE a.Id=‘1001’;
SELECT a.money INTO account_b FROM account_money a WHERE a.Id=‘1002’;
Dbms_Output.Put_Line(‘转账后A账户余额:’||account_a);
Dbms_Output.Put_Line(‘转账后B账户余额:’||account_b);
Dbms_Output.Put_Line(‘转账后总余额:’||(account_a+account_b));
EXCEPTION
WHEN OTHERS THEN
Dbms_Output.Put_Line(‘转账失败,业务取消’);
SELECT a.money INTO account_a FROM account_money a WHERE a.Id=‘1001’;
SELECT a.money INTO account_b FROM account_money a WHERE a.Id=‘1002’;
Dbms_Output.Put_Line(‘停止转账后A账户余额:’||account_a);
Dbms_Output.Put_Line(‘停止转账后B账户余额:’||account_b);
Dbms_Output.Put_Line(‘停止转账后总余额:’||(account_a+account_b));
END;
执行上段代码,执行第一遍后,结果如图4-18所示。

图4-18第一次执行账户金额
执行第二遍,结果4-18如图所示。

图4-19第二次执行账户金额

执行第7遍,结果4-20如图所示。

图4-20第七次执行账户金额

结论:当做事务处理后,总额不会发生变化,当出现异常就不会再执行(或者说回滚)。
4.5.2事务的组成和使用
1)数据库事务由以下的部分组成:
一个或多个DML 语句 ;
一个 DDL(Data Definition Language – 数据定义语言) 语句;
一个 DCL(Data Control Language – 数据控制语言)语句;
2)事务的执行开始:
以第一个 DML 语句的执行作为开始 ,以下面的其中之一作为结束:
COMMIT 或 ROLLBACK 语句;
DDL 或 DCL 语句自动提交;
3)事务的执行过程
COMMIT:保存自上一次COMMIT或ROLLBACK以来的所有改变。
ROLLBACK:回滚所有自上一次COMMIT或ROLLBACK以来的所有改变。对dml语句进行的操作,都可以进行回退。
ROLLBACK TO SAVEPOINT:回滚所有的改变到一个已经保存的保存点。
4)事务结束的标志:
用户会话正常结束;
系统异常;
5)事务控制语句的设置
Set transaction:设置事务的属性
Set constrains:设置当前事务的约束模式,设置约束是修改数据的时候,立即起作用,还是当前事务结束后应用。
Savepoint :在事务中建立一个存储点,回滚时,可以指定回滚到什么地方,然后重新执行.
Release savepoint:删除一个存储点
Rollback:回滚事务。取消对数据库所做的任何修改
Commit:提交事务,把事务中对数据库的修改进行永久保存
数据异常:因为Oracle中支持多个事务并发执行,所以会出现下面的数据异常。
错读|脏读:当user1正在读数据库中的表A时,user2正在修改表A,user2修改完了,user1又读一遍表A,user1读出的是修改过的数据,而user2又撤消修改了,user1的读取表A,称为错读或者脏读。
非重复读|不重复读:是指一个事务读取数据库中的数据后,另一个事务则更新了数据,当第一个事务再次读取其中的数据时,就会发现数据已经发生了改变,这就是非重复读取。非重复读取所导致的结果就是一个事务前后两次读取的数据不相同。
假读|幻读:如果一个事务基于某个条件读取数据后,另一个事务则更新了同一个表中的数据,这时第一个事务再次读取数据时,根据搜索的条件返回了不同的行,这就是假读。
事务中遇到的这些异常与事务的隔离性设置有关,事务的隔离性设置越多,异常就出现的越少,但并发效果就越低,事务的隔离性设置越少,异常出现的越多,并发效果越高。


http://www.ppmy.cn/devtools/116656.html

相关文章

自然语言处理-基于注意力机制的文本匹配

背景: 任务三:基于注意力机制的文本匹配 输入两个句子判断,判断它们之间的关系。参考ESIM(可以只用LSTM,忽略Tree-LSTM),用双向的注意力机制实现。 参考 《神经网络与深度学习》 第7章 Reaso…

线程池任务执行出现异常,如何知道是哪个线程出了异常?

自定义线程工厂类,去实现ThreadFactory的接口,为每个线程设定setUncaughtExceptionHandler,记录异常信息。 public class CustomThreadFactory implements ThreadFactory { Override public Thread newThread(Runnable r) { Thread thread …

C++中类的创建和声明

目录 前言 一、类的概念 二、对象 前言 说实话,C和C语言有比较大的差别,在C语言中我们面向的是过程,即要怎么实现功能的过程,在C中,我们面向对象,将这些功能和函数封装起来,用到直接调用对象&…

嵌入式面试学习笔记(入门1)

目录 指针的大小问题 sizeof和strlen C语言分配内存的方式 数组(的)指针和指针(的)数组 union 指针的大小问题 指针对于不少新手而言是一道难关,但是不必恐惧于指针。他的本质其实就是一个地址。请冷静下来仔细思…

【大模型专栏—实战篇】从0到1带你QLoar微调

大模型专栏介绍 😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本文为大模型专栏子篇,大模型专栏将持续更新,主要讲解大模型从入门到实战打怪升级。如有兴趣,欢迎您的阅读。 &#x1f4…

Debezium日常分享系列之:将容器镜像移至 quay.io

Debezium日常分享系列之:将容器镜像移至 quay.io 在Debezium 3.0.0.Final发布之后,我们将不再向docker.io发布容器镜像更新。旧版本的Debezium 2.x和1.x镜像将继续保留在docker.io上;然而,所有未来的Debezium 2.7.x和3.x或更高版本…

python | huey,一个非常厉害的 任务调度 Python 库!

本文来源公众号“python”,仅用于学术分享,侵权删,干货满满。 原文链接:huey,一个非常厉害的 Python 库! 大家好,今天为大家分享一个非常厉害的 Python 库 - huey。 Github地址:h…

图片切换示例2【JavaScript】

这段代码实现了一个简单的图片切换效果。当用户将鼠标悬停在不同的小缩略图上时&#xff0c;主显示框&#xff08;#box&#xff09;的背景图片会切换为相应的缩略图所代表的图片。 实现效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"zh"…