【数据库】事务的四大特性<详解>
2023-09-11 14:17:55 时间
数据库事务
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(); //主动回滚
}
}
}
相关文章
- 开涛spring3(9.2) - Spring的事务 之 9.2 数据库事务概述
- c#实例化继承类,必须对被继承类的程序集做引用 .net core Redis分布式缓存客户端实现逻辑分析及示例demo 数据库笔记之索引和事务 centos 7下安装python 3.6笔记 你大波哥~ C#开源框架(转载) JSON C# Class Generator ---由json字符串生成C#实体类的工具
- 干货 | 认识数据库事务
- 数据库事务隔离级别(脏读、幻读、不可重复读)
- c#操作mysql数据库
- 【数据库】+Navicat 过期/14天试用期满
- 【Docker】安装Presto连接Hive、mysql、oracle、postgresql、SQL server等7种类型数据库
- HikariPool-1 - Connection is not available, request timed out after 30000ms——数据库事务与数据库连接
- 《SQL入门经典(第5版)》一一6.3 事务控制与数据库性能
- 架构之路(五):忘记数据库
- oracle整合简单,无关联的数据库访问
- 数据库不完全恢复 以及恢复到测试环境:
- 数据库事务
- JPA连接PG数据库时间类型查询报错的修改
- 数据库事务的隔离以及spring的事务传播机制
- 《数据库技术原理与应用教程(第2版)》——第3章 数据管理中的数据模型 3.1 数据模型的基本概念
- 数据库 'tempdb' 的事务日志已满。若要查明无法重用日志中的空间的原因
- SQL索引一步到位(此文章为“数据库性能优化二:数据库表优化”附属文章之一)
- 数据库中的事务、存储过程和触发器的简单使用
- SQL基础知识笔记:概述(层状/网状/关系模型)、数据类型、操作数据库能力(DDL/DML/DQL)、关系模型(主键、联合主键、外键、外键约束-性能影响、一对一、一对多、多对多、索引、索引效率)、实用SQL语句、事务(四个特性、四种隔离级别)
- 写数据库mq消息事务一致性解决方案
- 数据库三大范式及事务隔离级别
- 定时备份mysql数据库 并删除7天前的备份 (windows linux )
- 数据库连接池配置部分
- 一个可以兼容各种数据库事务的使用范例
- ligerui实现数据库端分页功能
- Redis(1.3)Redis的基本特性(事务、多数据库)
- 【数据库】MySQL概念知识语法-基础篇-事务,真的很详细,一篇文章你就会了
- 使用 pymysql 操作数据库 mysql 8.0.15 版本
- 数据库 'MessageManage' 的事务日志已满。若要查明无法重用日志中的空间的原因,请参阅 sys.databases 中的 log_reuse_wait_desc 列。
- 数据库之事务
- sqlserver解决未能为数据库 ‘数据库名‘ 中的对象 ‘数据库日志文件‘ 分配空间,因为文件组 ‘PRIMARY‘ 已满。附带收缩数据库日志方法
- 数据库事务的四大特性以及事务的隔离级别