网站首页 > java教程 正文
事务的概念
事务是访问并更新数据库中各个数据项的一个程序执行单元;在事务操作中,要么都做修改,要么什么都不做。
MySQL中只有使用了Innodb数据库引擎的数据库或表才支持事务;事务用来管理insert,update,delete语句;
事务的类型
数据库事务类型,有本地事务和分布式事务:
1、本地事务:就是普通事务,能保证单台数据库上的操作的ACID,被限定在一台数据库上;
2、分布式事务:涉及两个或多个数据库源的事务,即跨越多台同类或异类数据库的事务(由每台数据库的本地事务组成的),分布式事务旨在保证这些本地事务的所有操作的ACID,使事务可以跨越多台数据库;
Java的事务类型,有JDBC事务和JTA事务:
1、JDBC事务:数据库事务类型中的本地事务,通过Connection对象的控制来管理事务;
2、JTA事务:JTA指Java事务API(Java Transaction API),是Java EE数据库事务规范, JTA只提供了事务管理接口,由应用程序服务器厂商(如:WebSphere Application Server)提供实现,JTA事务比JDBC更强大,支持分布式事务。
Java EE事务类型有本地事务和全局事务:
1、本地事务:使用JDBC编程实现事务;
2、全局事务:由应用程序服务器提供,使用JTA事务;
Java EE按是否通过编程实现事务有声明式事务和编程式事务:
1、声明式事务: 通过注解或XML配置文件指定事务信息;
2、编程式事务:通过编写代码实现事务;
事务具有ACID四个特性
分别是:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability):
原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的数据必须完全符合所有的预设规则,这包含数据的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
隔离性:允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
MySQL事务处理主要有两种方法:
1、用BEGIN, ROLLBACK, COMMIT来实现
BEGIN 开始一个事务
ROLLBACK 事务回滚
COMMIT 事务确认
2、直接用SET来改变MySQ的自动提交模式
SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT=1 开启自动提交
事务隔离级别
第一种隔离级别:Read uncommitted(读未提交),并发时存在问题:幻读、不可重复读、脏读
如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据,该隔离级别可以通过“排他写锁”,但是不排斥读线程实现。这样就避免了更新丢失,却可能出现脏读,也就是说事务B读取到了事务A未提交的数据。
第二种隔离级别:Read committed(读提交),并发时存在问题:幻读、不可重复读
如果是一个读事务(线程),则允许其他事务读写,如果是写事务将会禁止其他事务访问该行数据,该隔离级别避免了脏读,但是可能出现不可重复读。事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
第三种隔离级别:Repeatable read(可重复读取),并发时存在问题:幻读
可重复读取是指在一个事务内,多次读同一个数据,在这个事务还没结束时,其他事务不能访问该数据(包括了读写),这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别,读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务(包括了读写),这样避免了不可重复读和脏读,但是有时可能会出现幻读。(读取数据的事务)可以通过“共享读镜”和“排他写锁”实现。
第四种隔离级别:Serializable(可序化)
提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行,如果仅仅通过“行级锁”是无法实现序列化的,必须通过其他机制保证新插入的数据不会被执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也是最高的,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻读;
MySQL默认事务的隔离级别:REPEATABLE-READ
MySQL查看当前事务的隔离级别:SELECT @@tx_isolation;
JDBC事务隔离级别设置:
import com.what21.boot.jdbc.operate.JDBCHelper;
import java.sql.Connection;
import java.sql.SQLException;
/**
* 事务隔离(isolation)级别
*/
public class JDBCTransactionLevel {
/**
* 隔离(isolation)级别
*
* @param connection
* @throws SQLException
*/
public static int isolationLevel(Connection connection) throws SQLException {
int isolationLevel = connection.getTransactionIsolation();
if (isolationLevel == Connection.TRANSACTION_NONE) {
System.out.println("无事务,级别: " + isolationLevel + "=TRANSACTION_NONE");
} else if (isolationLevel == Connection.TRANSACTION_READ_UNCOMMITTED) {
System.out.println("读未提交,级别: " + isolationLevel + "=TRANSACTION_READ_UNCOMMITTED");
} else if (isolationLevel == Connection.TRANSACTION_READ_COMMITTED) {
System.out.println("读已提交,级别:" + isolationLevel + "=TRANSACTION_READ_COMMITTED");
} else if (isolationLevel == Connection.TRANSACTION_REPEATABLE_READ) {
System.out.println("可重复读,级别:" + isolationLevel + "=TRANSACTION_REPEATABLE_READ");
} else if (isolationLevel == Connection.TRANSACTION_SERIALIZABLE) {
System.out.println("可串行化,级别:" + isolationLevel + "=TRANSACTION_SERIALIZABLE");
}
return isolationLevel;
}
public static void main(String[] args) {
// SELECT @@tx_isolation;
// REPEATABLE-READ
Connection connection = JDBCHelper.createConnection();
try {
System.out.println(isolationLevel(connection));
} catch (SQLException e) {
e.printStackTrace();
}
JDBCHelper.close(connection);
}
}
JDBC的事务支持
1、自动提交模式(Auto-commit mode)
2、事务隔离级别(Transaction Isolation Levels)
3、保存点(SavePoint)
JDBC定义了SavePoint接口,提供在一个更细粒度的事务控制机制。当设置了一个保存点后,可以rollback到该保存点处的状态,而不是rollback整个事务。
代码案例:
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
public class JDBCTransactionSupportDemo {
/**
* 自动提交模式(Auto-commit mode)
*/
public static void supportMethod1() {
Connection connection = JDBCHelper.createConnection();
try {
connection.setAutoCommit(true);
insert(connection);
} catch (SQLException e) {
e.printStackTrace();
}
JDBCHelper.close(connection);
}
/**
* @param connection
*/
public static void insert(Connection connection) throws SQLException {
Statement stat = connection.createStatement();
String sql = "insert into users(name,email,phone,mobile) value('name','email','phone','mobile')";
stat.execute(sql);
JDBCHelper.close(stat);
}
/**
* 事务隔离级别(Transaction Isolation Levels)
*/
public static void supportMethod2() {
Connection connection = JDBCHelper.createConnection();
try {
connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
connection.setAutoCommit(false);
insert(connection);
} catch (SQLException e) {
e.printStackTrace();
try {
connection.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
} finally {
try {
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
JDBCHelper.close(connection);
}
/**
* 保存点(SavePoint)
*/
public static void supportMethod3() {
Connection connection = JDBCHelper.createConnection();
Savepoint oneSavepoint = null;
Savepoint twoSavepoint = null;
Savepoint threeSavepoint = null;
try {
connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
connection.setAutoCommit(false);
// 设置保存点
oneSavepoint = connection.setSavepoint("one");
insert(connection);
twoSavepoint = connection.setSavepoint("two");
insert(connection);
// 释放保存点
connection.releaseSavepoint(oneSavepoint);
threeSavepoint = connection.setSavepoint("three");
insert(connection);
} catch (RuntimeException e) {
e.printStackTrace();
try {
connection.rollback(threeSavepoint);
} catch (SQLException ex) {
ex.printStackTrace();
}
} catch (SQLException e) {
e.printStackTrace();
try {
connection.rollback(twoSavepoint);
} catch (SQLException ex) {
ex.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
try {
connection.rollback(oneSavepoint);
} catch (SQLException ex) {
ex.printStackTrace();
}
} finally {
try {
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
JDBCHelper.close(connection);
}
public static void main(String[] args) {
supportMethod1();
supportMethod2();
supportMethod3();
}
}
猜你喜欢
- 2024-11-14 Spring中的事务处理机制(spring事务管理 详解)
- 2024-11-14 小白都能看懂的JDBC事务(jdbc事务是什么)
- 2024-11-14 终于有人把分布式事务说清楚了(分布式事务是什么意思)
- 2024-11-14 JavaWeb分布式事务处理(java分布式事务实现案例)
- 2024-11-14 分布式事务(分布式事务的解决方案)
- 2024-11-14 分布式事务之三阶段提交,你了解多少?
- 2024-11-14 Kafka 的生成者、消费者、broker 的基本概念
- 2024-11-14 MySQL事务(MySQL事务)
- 2024-11-14 Java事务回滚(java实现事务回滚)
- 2024-11-14 简单聊聊Java追加事务控制的方法(简单聊聊java追加事务控制的方法是)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)