当前位置:网站首页>【数据库】事务的四大特性<详解>
【数据库】事务的四大特性<详解>
2022-08-02 03:33:00 【Money、坤】
数据库事务
1.概念
事务是应用程序中一些列严密的操作,所有操作要么全部成功执行,要么全部执行失败。
2.事务的四大特性
- 原子性(Atomicity)
业务动作对应的SQL应该是一个整体,不可以再拆分,针对数据的修改是能是要么全部成功执行们要么全部执行失败。 - 一致性(Consistency)
数据的一致性体现在两个方面:
①利用数据库的一些特性来保证部分一致性需求:比如声明某个列为NOT NULL 来拒绝NULL值得插入等。
②绝大部分还是需要我们程序员在编写业务代码的时候来保证。 - 隔离性(Isolation)
当有多个DBMS的用户,同时对数据进行增删查改时,用户之间的操作是相对独立的,一个用户的操作对其他用户而言是不可见的。 - 持久性(Durability)
一个事务一旦提交成功,对数据库中的数据的改变是持久性的。
3.如何使用事务
- 方式一 数据库使用事务
--开启事务
START TRANSACTION;
--执行sql的语句
INSERT INTO records(rid,bid) VALUES(1,2);
UPDATE books SET count=count-1 WHERE bid=2;
--rollback; //手动回滚
--提交事务
COMMIT; //代表一个事务的结束
注意点:
1.事务开启后,一旦执行SQL语句出现错误,事务中所有的操作都将回滚到数据操作前;
2.数据没有提交前,对数据库中的所有操作都不会写进磁盘,一旦发生某些错误,数据将恢复到操作前的状态;
3.数据库使用事务时,提交事务后,如果发生某些SQL的执行错误,系统将自动回滚;
- 方式二 通过JDBC使用事务
1.创建连接数据库的工具类
package com.qk.utils;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class DbUtils {
private static final DataSource DATA_SOURCE;
static {
MysqlDataSource db=new MysqlDataSource();
String url="jdbc:mysql://localhost:3306/beta?useSSL=false&characterEncodiing=utf-8&severTimezone=Asia/Shanghai";
db.setUrl(url);
db.setUser("root");
db.setPassword("787426");
DATA_SOURCE =db;
}
public static Connection getConnection() throws SQLException {
return DATA_SOURCE.getConnection();
}
}
2.测试事务提交
package com.qk;
import com.qk.utils.DbUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Demo1 {
public static void main(String[] args) throws SQLException {
String sql1="insert into records(rid,bid) values(1,2)";
String sql2="update books set count=count-1 where bid =2";
//同一个事务中,执行sql1和sql2,意味着必须在同一个Connection中完成
try(Connection connection = DbUtils.getConnection()) {
//connection中有一个autocommit属性,默认情况下是开启(true)
//开启状态下,意味着每一条sql都被视作一个事务
//要让sql1和sql2看作一个整体,就需关闭自动提交,手动提交事务
connection.setAutoCommit(false);
try(PreparedStatement ps=connection.prepareStatement(sql1)) {
ps.executeUpdate();
}
try(PreparedStatement ps=connection.prepareStatement(sql2)) {
ps.executeUpdate();
}
//手动提交事务,以上数据操作才算真正执行,数据写入磁盘
connection.commit();
}
}
}
3.JDBC事务使用的四个场景
- 有事务,commit成功
demo1,事务成功提交。 - 没有事务,被动失败(重启服务器)
demo2,没有执行事务,重启服务器后,sql2执行失败,数据库数据未成功更新
package com.qk;
import com.qk.utils.DbUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Demo2 {
public static void main(String[] args) throws SQLException {
String sql1="insert into records(rid,bid) values(1,2)";
String sql2="update books set count=count-1 where bid =2";
try(Connection connection = DbUtils.getConnection()) {
try(PreparedStatement ps=connection.prepareStatement(sql1)) {
ps.executeUpdate();
}
//执行完第一天sql1后,第二天sql2执行失败
try(PreparedStatement ps=connection.prepareStatement(sql2)) {
ps.executeUpdate();
}
}
}
}
- 有事务,被动失败(重启服务器)程序出错
demo3,开启事务,重启服务器或程序出现错误后,数据会发生回滚
package com.qk;
import com.qk.utils.DbUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Demo3 {
public static void main(String[] args) throws SQLException {
String sql1="insert into records(rid,bid) values(1,2)";
String sql2="update books set count=count-1 where bid =2";
try(Connection connection = DbUtils.getConnection()) {
//开启事务
connection.setAutoCommit(false);
try(PreparedStatement ps=connection.prepareStatement(sql1)) {
ps.executeUpdate();
}
//执行完第一天sql1后,第二天sql2执行失败
try(PreparedStatement ps=connection.prepareStatement(sql2)) {
ps.executeUpdate();
}
connection.commit();
}
}
}
- 有事务,主动失败(rollback)
demo4,开启事务,执行完sql语句后,主动回滚事务,所有数据操作都将回滚到操作前
package com.qk;
import com.qk.utils.DbUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Demo4 {
public static void main(String[] args) throws SQLException {
String sql1="insert into records(rid,bid) values(1,2)";
String sql2="update books set count=count-1 where bid =2";
try(Connection connection = DbUtils.getConnection()) {
//开启事务
connection.setAutoCommit(false);
try(PreparedStatement ps=connection.prepareStatement(sql1)) {
ps.executeUpdate();
}
try(PreparedStatement ps=connection.prepareStatement(sql2)) {
ps.executeUpdate();
}
connection.rollback(); //主动回滚
}
}
}
边栏推荐
- 如何快速搭建属于自己的物联网平台?
- 【Popular Science Post】UART Interface Communication Protocol
- 增量编译技术在Lightly中的实践
- Comparative analysis of mobile cloud IoT pre-research and Alibaba Cloud development
- I2C无法访问ATEC508A加密芯片问题
- MPU6050 加速度计和陀螺仪传感器与 Arduino 连接
- 振芯科技GM8285C:功能TTL转LVDS芯片简介
- 所有子字符串中的元音 —— LeetCode - 2063
- MQ-5 可燃气体传感器与 Arduino 接口
- AD8307对数检波器
猜你喜欢
NE5532运放加法器
振芯科技GM8285C:功能TTL转LVDS芯片简介
2020 - AAAI - 图像修复 Image Inpainting论文导读 -《Region Normalization for Image Inpainting》
Anaconda(Jupyter)里发现不能识别自己的GPU该怎么办?
78XX 79XX多路输出电源
PCIE电路设计
[Arduino connected to GPS module (NEO-6M) to read positioning data]
基于阿里云OSS+PicGo的个人图床搭建
【Arduino连接时钟模块在LCD1602上显示时间】
【Popular Science Post】Detailed explanation of MDIO interface
随机推荐
install 命令
2019 - ICCV - 图像修复 Image Inpainting 论文导读《StructureFlow: Image Inpainting via Structure-aware ~~》
D类音频功放NS4110B电路设计
【科普贴】SPI接口详解
VCA821可变增益放大器
HDMI转MIPI CSI东芝转换芯片-TC358743XBG/TC358749XBG
“520” 如何正确地用代码向 ta 表白?
分割回文串 DP+回溯 (LeetCode-131)
【plang1.4.3】编写水母动画脚本
【Popular Science Post】Detailed explanation of MDIO interface
GM8775C MIPI转LVDS调试心得分享
Mac安装MySQL详细教程
ICN6211:MIPI DSI转RGB视频转换芯片方案介绍 看完涨知识了呢
【Arduino 连接DHT11 湿度和温度传感器】
倍福ET2000侦听器使用
【plang 1.4.3】定时器的使用
USB2.0一致性测试方法_高速示波器
使用批处理脚本修改hosts文件
引擎开发日志:重构骨骼动画系统
IDEA2021.2安装与配置(持续更新)