MySQL事物提交与回滚

(一)什么是事物?

事务是逻辑上的一组操作,组成这组操作的各个单元,要不全都成功要不全都失败,这个特性就是事务。事务是必须满足4个条件(ACID): Atomicity(原子性)、Consistency(稳定性)、Isolation(隔离性)、Durability(可靠性)。

(二)事物提交与回滚

在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。

例子:默认JDBC设置

	public static void main(String[] args) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			conn = DBUtil.getConn();
			//conn.setAutoCommit(false);//设置自动事务提交为false
			//a给b转账-----a账户减去100块钱;b账户增加100块钱
			ps = conn.prepareStatement("update account set salary=salary-100 where name=?");
			ps.setString(1, "a");
			ps.executeUpdate();
			
			int i = 1 / 0;	//设置异常
			
			ps = conn.prepareStatement("update account set salary=salary+100 where name=?");
			ps.setString(1, "b");
			ps.executeUpdate();
			
			conn.commit();
		} catch (Exception e) {
			e.printStackTrace();
			try {
				conn.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		} finally {
			DBUtil.close(conn, ps, rs);
		}
	}

代码解析:默认情况下每执行一条sql语句,就是执行一次事务,也就是每一条sql语句的执行都会是一次事务的提交。在这个例子中如果a给b转账,a账户减去100的sql语句执行成功,这时伴随着一次的事务提交,数据库中的a账户金额减去100;而再执行b的账务增加100sql语句之前,出现了异常,这里我设了一个除以零异常,此时程序终止,bsql语句不再执行。a账户扣了100,而b账户则金额不变。这时数据出错。

解决方法是:通过conn.setAutoCommit(false);方法设置事务自动提交为false。这时每一次的sql语句执行完成后就不会提交事务,数据库中的数据并不会发生改变,当俩个sql都执行完成,然后调用coon.commit();方法提交事务,此时数据库中的数据才会真正的改变。如果中途发生异常,通过conn.rollback();方法回滚,此时之前执行的sql语句的结果并不会提交。这样数据就不会出错了。

知识点:当一个连接对象被创建时,默认情况下JDBC是自动提交事务:每次执行一个 SQL 语句时,如果执行成功,就会向数据库自动提交,而不能回滚。如想多条SQL在同一事务中,可使用下列语句:
☆JDBC控制事务语句
Connection.setAutoCommit(false);
Connection.rollback();
Connection.commit();

例子:设置setAutoCommit(false),和事物回滚点

public static void main(String[] args) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		Savepoint point = null;
		try {
			conn = DBUtil.getConn();
			conn.setAutoCommit(false);//设置自动事务提交为false
			
			//a给b转账-----a账户减去100块钱;b账户增加100块钱
			ps = conn.prepareStatement("update account set salary=salary-100 where name=?");
			ps.setString(1, "a");
			ps.executeUpdate();
			
			ps = conn.prepareStatement("update account set salary=salary+100 where name=?");
			ps.setString(1, "b");
			ps.executeUpdate();
			
			point = conn.setSavepoint();
			int i = 1 / 0;
			
			//a给b转账-----a账户减去100块钱;b账户增加100块钱
			ps = conn.prepareStatement("update account set salary=salary-100 where name=?");
			ps.setString(1, "a");
			ps.executeUpdate();
			
			ps = conn.prepareStatement("update account set salary=salary+100 where name=?");
			ps.setString(1, "b");
			ps.executeUpdate();
			
			conn.commit();
		} catch (Exception e) {
			e.printStackTrace();
			try {
				if(point == null) {
					conn.rollback();
				} else {
					conn.rollback(point);
					conn.commit();
				}
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
		} finally {
			DBUtil.close(conn, ps, rs);
		}
	}

知识点:

☆设置事务回滚点

Savepoint sp = conn.setSavepoint();
Conn.rollback(sp);  //回滚
Conn.commit();   //回滚后必须要提交

(三)在MYSQL 事务处理主要有两种方法:

1、用 BEGIN, ROLLBACK, COMMIT来实现

  • BEGIN 开始一个事务
  • ROLLBACK 事务回滚
  • COMMIT 事务确认

2、直接用 SET 来改变 MySQL 的自动提交模式:

  • SET AUTOCOMMIT=0 禁止自动提交
  • SET AUTOCOMMIT=1 开启自动提交

例子: 

mysql> use RUNOOB;
Database changed
mysql> CREATE TABLE runoob_transaction_test( id int(5)) engine=innodb;  # 创建数据表
Query OK, 0 rows affected (0.04 sec)
 
mysql> select * from runoob_transaction_test;
Empty set (0.01 sec)
 
mysql> begin;  # 开始事务
Query OK, 0 rows affected (0.00 sec)
 
mysql> insert into runoob_transaction_test value(5);
Query OK, 1 rows affected (0.01 sec)
 
mysql> insert into runoob_transaction_test value(6);
Query OK, 1 rows affected (0.00 sec)
 
mysql> commit; # 提交事务
Query OK, 0 rows affected (0.01 sec)
 
mysql>  select * from runoob_transaction_test;
+------+
| id   |
+------+
| 5    |
| 6    |
+------+
2 rows in set (0.01 sec)
 
mysql> begin;    # 开始事务
Query OK, 0 rows affected (0.00 sec)
 
mysql>  insert into runoob_transaction_test values(7);
Query OK, 1 rows affected (0.00 sec)
 
mysql> rollback;   # 回滚
Query OK, 0 rows affected (0.00 sec)
 
mysql>   select * from runoob_transaction_test;   # 因为回滚所以数据没有插入
+------+
| id   |
+------+
| 5    |
| 6    |
+------+
2 rows in set (0.01 sec)

 

转载于:https://my.oschina.net/u/2937897/blog/1537935

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值