张晨光-JAVA零基础保姆式技术教程之-事务

news2024/12/25 15:55:45

事务

课程目标

1、什么是事务
2、jdbc如何控制事务
3、设置事务的回滚点
4、事务的特性ACID
5、数据库事务的隔高级别

事务理解

什么是事务: 指逻辑上一组操作,要么同时成功,要么同时失败。

举例: 转账 a 给b 转账 100  a原来有1000 b原来也有1000
account 是一个表名 表示的 账务表,里面有人的信息,和人的金额。
update account set money=money-100 where name = a;
update account set money =money+100 where name=b;

假设:
update account set money=money-100 where name = a;
出现了异常。
update account set money =money+100 where name=b;
后果: a的余额是900   b的余额 1000

有了事务:

开启事务:
update account set money=money-100 where name = a;
出现了异常。 ---- 事务进行管理: 进行回滚: 更改的记录无效。
update account set money =money+100 where name=b;

此时:a的余额是1000  b的余额 1000

mysql中事务

-- mysql中,默认事务是自动提交的。一条sql一个事务。

开启事务
操作
提交事务;


start transaction  -- 开启一个事务。以后的sql都在一个事务中。更改的内容不会自动提交。
rollback        -- 事务的回滚—同时失败的情况。--事务结束,并且全部失败,数据回复到开始之前的状态
commit -- 事务的提交----同时成功---事务结束。全部成功。

-- 账务信息
create table account(
	name varchar(10),
	money double
);

insert into account(name,money) values('a',1000);
insert into account(name,money) values('b',1000);

去做a给b转100块。

-- mysql默认类似这样
start transaction ;
update account set money = money -100 where name = ‘a’;
commit;
start transaction ;
update account set money = money +100 where name = ‘b’;
commit;

-- 自身手动控制事务。
start transaction ;
update account set money = money -100 where name = ‘a’;

update account set money = money +100 where name = ‘b’;
commit;

代码实现

在这里插入图片描述

在这里插入图片描述

jdbc事务管理

API方法

jdbc中的事务是通过Connection对象进行事务管理的

conn.setAutoCommit(false)//相当于start transaction  开启事务
conn.rollback(); //rollback  事务回滚
conn.commit(); //commit   事务提交

代码实现

没有事务

  /**
     * 案例:jack 给  rose 转帐     没有事务
     */
    @Test
    public void test1()  {

        Connection conn = null;
        Statement stmt = null;
        try {
            conn = JDBCUtil.getConnection();

            stmt = conn.createStatement();

            String sql ="update account set money = money -100 where name = 'jack'";
            stmt.executeUpdate(sql);

            //人为的给出一个异常
            int a = 10/0;//除数不能为0

            String sql2 ="update account set money = money +100 where name = 'rose'";
            stmt.executeUpdate(sql2);

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JDBCUtil.close(stmt,conn);
        }
    }

手动事务

  /**
     * 案例:jack 给  rose 转帐     添加事务
     */
    @Test
    public void test2()  {

        Connection conn = null;
        Statement stmt = null;
        try {
            conn = JDBCUtil.getConnection();

            //[开启事务]
            conn.setAutoCommit(false);

            //[操作数]
            stmt = conn.createStatement();

            String sql ="update account set money = money -100 where name = 'jack'";
            stmt.executeUpdate(sql);

            //人为的给出一个异常
            int a = 10/0;

            String sql2 ="update account set money = money +100 where name = 'rose'";
            stmt.executeUpdate(sql2);

            //没有问题,就提交
            conn.commit();

        } catch (SQLException e) {
            //如果中间发生的异常,回滚到前面的操作
            try {
                conn.rollback();
                conn.commit();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }

            e.printStackTrace();
        }finally {
            JDBCUtil.close(stmt,conn);
        }
    }

事务回滚点

一次性去执行多条(10000)sql语句的时候。一出现异常,10000条全部回滚。
如果出现的问题,设置一个回滚点,回滚到那一个点,就行了,这就避免全部回滚

API

Savepoint sp = conn.setSavepoint() // 设置回滚点
conn.rollback(sp);//回滚到设置的点
conn.commit();//回滚后必须提交

案例实现

需求:向数据库发送10000条数据,每1000条是合理的

/**
 * @Auther: yanqi
 * @Desc 向数据库发送10000条数据,每1000条做一个回滚点
 */
public class Demo2 {

    @Test
    public void test1(){
        Connection conn = null;
        PreparedStatement psmtm = null;
        Savepoint sp = null;
        try {
            conn= JDBCUtil.getConnection();
            String sql ="insert into t_user (username) values( ? )";
            psmtm = conn.prepareStatement(sql);

            //开启事务
            conn.setAutoCommit(false);

            for (int i = 1; i <1000 ; i++) {

                if(i == 999){
                    int a = 1/0;
                }

                psmtm.setString(1,i+"江一燕");
                psmtm.executeUpdate();

                //每100条设置一个保存点
                if(i%100 == 0){
                    sp = conn.setSavepoint();
                }
            }

            //事务提交
            conn.commit();

        } catch (Exception e) {
            //事务回滚
            try {
                conn.rollback(sp);//此时只回滚100条数据
                conn.commit();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }

            e.printStackTrace();
        }finally {
            JDBCUtil.close(psmtm,conn);
        }
    }
}

事务的特性ACID

原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位(最小的一个整体),事务中的操作要么都发生,要么都不发生。 
一组操作时一个整体。不能分割。

一致性(Consistency)
事务前后数据的完整性必须保持一致。
一致性和原子性相关。只有都成功或者,都失败(原子性) ,就可以保证事务的一致性。
事务的前后的内容一直。 
转账: a 1000 b 1000 a给b转100;
转账之前 a和b的总额 2000
转账之后 也要2000;

隔离性(Isolation)
事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。

多个事务是独立存在的。多个事务不能够相互干扰。
a –b---事务A
c-d---事务B
如果A失败了。不能够影响B

持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。 
a-100
b+100
提交
此时a永远少100
b永远的多了100

a – 100  a 900 
b+100   b 1100
commit;

a -100 a 800
b+100 b 1200
rollback : a 900  b 1100

rollback—异常。对上述没有任何影响了。

事务的隔离级别

如果不考虑事务的隔离性,将会产生以下问题:

由数据事务的并发造成的问题。

1、脏读,—最严重的事情
2、不可重复读
3、幻读(虚读)

脏读

一个事务读取了另外一个事务没有的提交的数据。非常严重。尽可能去避免掉脏读

在这里插入图片描述

不可重复读

一个事务读取另外一个提交过的数据。造成另外一个事务,多次读取的【内容】不一致,数据的内容的改变。 update

在这里插入图片描述

幻读(虚读)

一个事务读取另外一个事务已经提交的数据。但是这里面强调的数据数目的改变。insert,delete。

1、开始统计 100
​ 用户下单 提交
2、查询 101
在这里插入图片描述

虚读和不可重复读

不可重复读: 同一条记录 内容的改变 --update

虚读: 条目数的改变—insert delete

数据库的事务隔离级别

数据库共定义了四种隔离级别:
Serializable:可避免脏读、不可重复读、虚读情况的发生。    (可串行化,一个事务一个事务运行)
Repeatable read:可避免脏读、不可重复读情况的发生。      (可重复读)【不可以避免虚读】
Read committed:可避免脏读情况发生。                     (读已提交)【避免不了虚读以及不可重复读】
Read uncommitted:最低级别,以上情况均无法保证。          (读未提交)
设置事务的隔离级别
set session transaction isolation level 设置事务隔离级别    两个人
select @@tx_isolation	查询当前事务隔离级别

设置【读未提交】隔离级别

1、Read uncommitted (读未提交) 最低级别,以上情况均无法保证。 两个人的操作都是一样的

set session transaction isolation level Read uncommitted;
select @@tx_isolation;
start transaction;
update account set money = money-100 where name ='jack';
update account set money = money+100 where name ='rose';
rollback;
set session transaction isolation level Read uncommitted;
select @@tx_isolation;
start transaction;
select * from account;

在这里插入图片描述

设置【读已提交】隔离级别

2、Read committed;(读已提交) 可避免脏读情况发生(避免不了虚读以及不可重复读)

set session transaction isolation level Read committed;
select @@tx_isolation;
start transaction;
update account set money = money-100 where name ='jack';
update account set money = money+100 where name ='rose';
commit;
set session transaction isolation level Read committed;
select @@tx_isolation;
start transaction;
select * from account;

在这里插入图片描述

设置【可重复读】隔高级别

3、Repeatable read :可以避免脏读,不可重复度。

set session transaction isolation level Repeatable read;
select @@tx_isolation;
start transaction;
update account set money = money-100 where name ='jack';
update account set money = money+100 where name ='rose';
commit;
set session transaction isolation level Repeatable read;
select @@tx_isolation;
start transaction;
select * from account;

在这里插入图片描述

在mysql中。mysql数据库本身,对虚读已经进行了优化处理。所以展示不出虚读的发生。mysql处理的也不是特别好。

设置【可串行化】隔高级别

4:串行化的可以避免所有的问题。 数据库让其他的事务进行等待,等待一个事务结束之后,这个事务再去操作。

set session transaction isolation level Serializable;
select @@tx_isolation;
start transaction;
update account set money = money-100 where name ='jack';
update account set money = money+100 where name ='rose';
commit;
set session transaction isolation level Serializable;
select @@tx_isolation;
start transaction;
select * from account;

在这里插入图片描述

一个事务一事务的执行,只上一个事务结束了,另一个事务才可以操作,避免了所有问题

隔离级别的性能问题

性能比较
Serializable  性能最差:事务一个一个执行的。排队。

Serializable  < Repeatable read < Read committed < Read uncommitted

安全性比较
Serializable 安全性最好:所有问题避免掉。

Serializable > Repeatable read > Read committed > Read uncommitted

Read uncommitted 避免不了最重问题,脏读。
Serializable:性能太差。

mysql (默认)-- Repeatable read;(可重复读)
oracle(默认) -- Read committed;(读已提交)

一个事务一事务的执行,只上一个事务结束了,另一个事务才可以操作,避免了所有问题

隔离级别的性能问题

性能比较
Serializable  性能最差:事务一个一个执行的。排队。

Serializable  < Repeatable read < Read committed < Read uncommitted

安全性比较
Serializable 安全性最好:所有问题避免掉。

Serializable > Repeatable read > Read committed > Read uncommitted

Read uncommitted 避免不了最重问题,脏读。
Serializable:性能太差。

mysql (默认)-- Repeatable read;(可重复读)
oracle(默认) -- Read committed;(读已提交)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/356092.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

React Native Cannot run program “node“问题

概述 前几天mac重装系统了&#xff0c;用Android studio重新构建React native项目时&#xff0c;报Cannot run program "node"错误。 电脑系统为macOS 12.6.3 (Monterey)&#xff0c;M1 Pro芯片。设备信息如下图所示&#xff1a; 完整错误信息如下图所示&#xff…

链表OJ(七)删除有序链表中重复的元素-I -II

目录 删除有序链表中重复的元素-I 删除有序链表中重复的元素-II 删除有序链表中重复的元素-I 描述 删除给出链表中的重复元素&#xff08;链表中元素从小到大有序&#xff09;&#xff0c;使链表中的所有元素都只出现一次 例如&#xff1a; 给出的链表为1→1→21→1→2,返回1…

码农饭碗不保——ChatGPT正在取代Coder

码农饭碗不保——ChatGPT正在取代Coder 最近被OpenAI的ChatGPT刷屏了。我猜你已经读了很多关于ChatGPT的文章&#xff0c;不需要再介绍了。假如碰巧您还不太了解ChatGPT是什么&#xff0c;可以先看一下这篇文章&#xff0c;然后再回来继续。 与ChatGPT对话很有趣&#xff0c;…

【尊享版】如何从零到一掌控习惯?

超友们&#xff0c;早上好&#xff5e; 今天为你带来的分享是《如何从零到一掌控习惯&#xff1f;》&#xff0c;主要分为八个部分&#xff1a; 一、【为什么要培养习惯&#xff1f;】 二、【养成新习惯为什么很难&#xff1f;】 三、【习惯养成的原理是什么&#xff1f;】 …

D3.js绘图流程

简介 D3.js是由javaScript语言编写绘图库&#xff0c;其原理是&#xff1a;通过调用一系列内置函数&#xff0c;生成SVG&#xff0c;并在网页渲染。 本文以频率分布直方图案例为例&#xff0c;介绍使用D3.js的流程 流程 第一步 引用D3.js库 建立一个html文件&#xff0c;在…

【Flutter】入门Dart语言:初步了解内建类型

文章目录一、概述1.为什么叫内建类型&#xff1f;2.Dart的内建类型有哪些&#xff1f;二、内建类型详解1.num2.int3.double4.String5.bool6.List7.Map8.Function三、总结一、概述 "The greatest glory in living lies not in never falling, but in rising every time we…

分享111个HTML体育竞技模板,总有一款适合您

分享111个HTML体育竞技模板&#xff0c;总有一款适合您 111个HTML体育竞技模板下载链接&#xff1a;https://pan.baidu.com/s/1JmjlNVApPLVWnSEN5VlILQ?pwd5kzl 提取码&#xff1a;5kzl Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 响应式户外攀岩运动宣传…

【亲测有效】错误代码0x904,远程桌面连接异常终端问题

【亲测有效】错误代码0x904&#xff0c;远程桌面连接异常终端问题一、问题情况二、解决办法1.打开防火墙&#xff0c;如图&#xff0c;点击“允许应用或功能通过Windows”2.点击“允许其他应用”3.点击“浏览”4.在如下目录找到“mstsc.exe”添加5.点击“添加”6.勾选“专用”和…

[软件工程导论(第六版)]第5章 总体设计(课后习题详解)

文章目录1. 为每种类型的模块耦合举一个具体例子。2. 为每种类型的模块内聚举一个具体例子。3. 用面向数据流的方法设计下列系统的软件结构。4. 美国某大学共有200名教师&#xff0c;校方与教师工会刚刚签订一项协议。按照协议&#xff0c;所有年工资超过$26000&#xff08;含$…

电商搜索和推荐场景下的MLOps实践

省时查报告-专业、及时、全面的行研报告库省时查方案-专业、及时、全面的营销策划方案库【免费下载】2023年1月份热门报告合集ChatGPT的发展历程、原理、技术架构及未来方向《ChatGPT&#xff1a;真格基金分享.pdf》2023年AIGC发展趋势报告&#xff1a;人工智能的下一时代2023年…

图的基本概念和性质

目录一、图的引入1.引言2.不同类型的图3.无序对和无序积4.什么是图二、图的表示1.图的表示2.邻接矩阵3.邻接点与邻接边4.一些简单的特殊图三、图的分类1.按边有无方向分类2.按有无平行边分类3.按有无权值分类4.综合分类方法四、子图和补图1.各类子图2.完全图3.补图4.补图的邻接…

WSL(ubuntu2204)xfce4安装中文环境和fcitx5框架及中文输入法

安装中文语言包 sudo apt install language-pack-zh-hans 配置中文显示 首先运行如下命令配置 locale $ sudo vi /etc/locale.gen 找到 *zh_CN.UTF-8 UTF-8* 并取消注释&#xff0c;然后保存并退出。 locale.gen... # zh_CN.GBK GBK zh_CN.UTF-8 UTF-8 # zh_HK BIG5-HKS…

【C语言刷题】倒置字符串

解题思路与过程&#x1f4fd;️解题思路&#x1f4fd;️解题过程&#x1f527;1.输入&#x1f527;2.设计逆序函数&#x1f527;3.逆序整个字符串&#x1f527;4.逆序每个单词&#x1f4fd;️源码&#x1f4f7;先来看题&#x1f447;&#x1f4fd;️解题思路 &#x1f534; 首先…

【验证码的识别】—— 图形验证码的识别

前言 &#xff08;结尾有彩蛋欧&#xff09; 目前&#xff0c;许多网站采取各种各样的措施来反爬虫&#xff0c;其中一个措施便是使用验证码。随着技术的发展&#xff0c;验证码的花样越来越多。验证码最初是几个数字组合的简单的图形验证码&#xff0c;后来加入了英文字母和混…

RK356x U-Boot研究所(命令篇)3.6 fdt命令的用法

平台U-Boot 版本Linux SDK 版本RK356x2017.09v1.2.3文章目录 一、fdt命令的配置二、fdt命令的定义三、fdt命令的用法3.1 fdt list3.2 fdt rm3.3 fdt set一、fdt命令的配置 .config配置文件需要有以下配置: rk3568_defconfig默认已使能。 二、fdt命令的定义 usb命令定义在cm…

169、【动态规划】leetcode ——123. 买卖股票的最佳时机 III:二维数组+一维数组 (C++版本)

题目描述 原题链接&#xff1a;123. 买卖股票的最佳时机 III 解题思路 &#xff08;1&#xff09;二维dp数组 动态规划五步曲&#xff1a; &#xff08;1&#xff09;dp数组含义&#xff1a; dp[i][0]&#xff0c;表示无操作。主要由四个状态来表示四种操作。dp[i][1]&…

博客系统web自动化测试

目录 一、项目简介 二、测试用例 三、测试过程 3.1 环境搭建 3.2 编写代码 3.2.1 博客登陆页面测试 3.2.2 博客列表页面测试 3.2.3 博客详情页面测试 3.2.4 博客编辑页面测试 四、测试评估 一、项目简介 本项目是一个简易的个人博客系统&#xff0c;用户可以在登陆后…

W800开发板|SDK| HLK-W800-KIT-PRO|工具链|本地命令行编译|Windows11|WSL|(5)、海凌科W800开发板命令行编译指南

概况 海凌科W800开发板&#xff08;HLK-W800-KIT&#xff09;是海凌科电子面向开发者针对联盛德W800 芯片推出的一款多功能开发板。全功能版本与联盛德W800开发板相比&#xff0c;增加了温湿度传感器、RGB 灯以及音频解码器、功放可以直接在开发版验证功能。联盛德W800的csdk也…

java虚拟机内存分布

java虚拟机内存分布 Java虚拟机在执行java程序的过程中会把它所管理的内存划分为如下若干个不同的数据区域。 1.程序计数器 程序计数器是线程私有的&#xff0c;它占用的空间相对较小&#xff0c;用来记录当前线程字节码执行到哪一步。字节码解释器通过改变这个计数器的值来获…

Portraiture2023最新版人像图像后期处理软件

2023全新发布Portraiture 4是专注于图像后期处理软件研发的 Imagenomic, LLC产品之一&#xff0c;在摄影爱好者中有点影响力。Portraiture可以将繁琐复杂的人像磨皮操作极致简化&#xff0c;不论是普通爱好者或专业后期处理人员&#xff0c;均能一键完成。凭借优秀的AI算法和多…