JDBC事务控制

来源:互联网 发布:php代码保护 编辑:程序博客网 时间:2024/06/04 18:09
 

JDBC事务控制

一、所谓事务:是指一组原子操作(一组SQL语句执行)的工作单元。

创建JDBC的事务主要分以下步骤:

设置事务的提交方式为非自动提交:conn.setAutoCommit(false); 

将需要添加事务的代码放在try、catch块中:
try {
      //需要添加事务的业务代码
} catch (SQLException e) {
      ...
}

在try块内添加提交操作,表示操作无异常,提交事务:conn.commit();   //正常流程,提交事务

在catch块内添加回滚事务,表示操作出现异常,撤消事务:conn.rollback();   //发生异常,撤消事务

设置事务提交方式为自动提交:conn.setAutoCommit(true);   //自动提交事务

任何一个任务的失败都会导致整个事务被撤销,系统返回到以前面状态。

二、事务和ACID属性

    “ACID”是一个简称,每个事务的处理必须满足ACID原则,即原子性(A)一致性(C)隔离性(I)持久性(D)

原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

     一致性:在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。

   隔离性:两个事务的执行是互不干扰的,一个事务不可能看到其他事务运行时,中间某一时刻的数据。

     持久性:在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

三、事务的处理

mysql> select @@autocommit;  //显示是否自动提交事务方式

+--------------+

| @@autocommit |

+--------------+

|            1 |

+--------------+

1 row in set

 

mysql> select * from student;   //查看库

+----+------+-----+--------+-----+----------+-------+

| id | name | sex | adress | tel | resume   | image |

+----+------+-----+--------+-----+----------+-------+

|  1 | 嘟嘟 | 男  | 石家庄 | 101 | 一个帅哥 | NULL  |

|  2 | 啾啾 | 女  | 保定   | 110 | 一个美女 | NULL  |

|  3 | 啦啦 | 女  | 大连   | 111 | 一个美女 | NULL  |

|  4 | 咚咚 | 男  | 北京   | 112 | 一个帅哥 | NULL  |

+----+------+-----+--------+-----+----------+-------+

4 rows in set

 

mysql> set @@autocommit=0;  //手动提交操作

Query OK, 0 rows affected

 

mysql> start transaction;   //事务开始

Query OK, 0 rows affected

 

mysql> update student   //表的更新

    -> set name='qq'

    -> where id=3;

Query OK, 1 row affected

Rows matched: 1  Changed: 1  Warnings: 0

 

mysql> select * from student;

+----+------+-----+--------+-----+----------+-------+

| id | name | sex | adress | tel | resume   | image |

+----+------+-----+--------+-----+----------+-------+

|  1 | 嘟嘟 | 男  | 石家庄 | 101 | 一个帅哥 | NULL  |

|  2 | 啾啾 | 女  | 保定   | 110 | 一个美女 | NULL  |

|  3 | qq   | 女  | 大连   | 111 | 一个美女 | NULL  |

|  4 | 咚咚 | 男  | 北京   | 112 | 一个帅哥 | NULL  |

+----+------+-----+--------+-----+----------+-------+

4 rows in set

 

mysql> commit;  //提交事务

Query OK, 0 rows affected

 

mysql> select * from student;

+----+------+-----+--------+-----+----------+-------+

| id | name | sex | adress | tel | resume   | image |

+----+------+-----+--------+-----+----------+-------+

|  1 | 嘟嘟 | 男  | 石家庄 | 101 | 一个帅哥 | NULL  |

|  2 | 啾啾 | 女  | 保定   | 110 | 一个美女 | NULL  |

|  3 | qq   | 女  | 大连   | 111 | 一个美女 | NULL  |

|  4 | 咚咚 | 男  | 北京   | 112 | 一个帅哥 | NULL  |

+----+------+-----+--------+-----+----------+-------+

4 rows in set

 

mysql> update student  //第二个事务

    -> set name='ff'

    -> where id=1;

Query OK, 1 row affected

Rows matched: 1  Changed: 1  Warnings: 0

 

mysql> select * from student;

+----+------+-----+--------+-----+----------+-------+

| id | name | sex | adress | tel | resume   | image |

+----+------+-----+--------+-----+----------+-------+

|  1 | ff   | 男  | 石家庄 | 101 | 一个帅哥 | NULL  |

|  2 | 啾啾 | 女  | 保定   | 110 | 一个美女 | NULL  |

|  3 | qq   | 女  | 大连   | 111 | 一个美女 | NULL  |

|  4 | 咚咚 | 男  | 北京   | 112 | 一个帅哥 | NULL  |

+----+------+-----+--------+-----+----------+-------+

4 rows in set

 

mysql> rollback;  //回滚事务  回到事务之前的状态

Query OK, 0 rows affected

 

mysql> select * from student;

+----+------+-----+--------+-----+----------+-------+

| id | name | sex | adress | tel | resume   | image |

+----+------+-----+--------+-----+----------+-------+

|  1 | 嘟嘟 | 男  | 石家庄 | 101 | 一个帅哥 | NULL  |

|  2 | 啾啾 | 女  | 保定   | 110 | 一个美女 | NULL  |

|  3 | qq   | 女  | 大连   | 111 | 一个美女 | NULL  |

|  4 | 咚咚 | 男  | 北京   | 112 | 一个帅哥 | NULL  |

+----+------+-----+--------+-----+----------+-------+

4 rows in set

 

mysql> delete from student

    -> where id=1;

Query OK, 1 row affected

 

mysql> select * from student;

+----+------+-----+--------+-----+----------+-------+

| id | name | sex | adress | tel | resume   | image |

+----+------+-----+--------+-----+----------+-------+

|  2 | 啾啾 | 女  | 保定   | 110 | 一个美女 | NULL  |

|  3 | qq   | 女  | 大连   | 111 | 一个美女 | NULL  |

|  4 | 咚咚 | 男  | 北京   | 112 | 一个帅哥 | NULL  |

+----+------+-----+--------+-----+----------+-------+

3 rows in set

 

mysql> rollback work to savepoint s1;  //事务回滚到s1

Query OK, 0 rows affected

 

mysql> select * from student;

+----+------+-----+--------+-----+----------+-------+

| id | name | sex | adress | tel | resume   | image |

+----+------+-----+--------+-----+----------+-------+

|  1 | aa   | 男  | 石家庄 | 101 | 一个帅哥 | NULL  |

|  2 | 啾啾 | 女  | 保定   | 110 | 一个美女 | NULL  |

|  3 | qq   | 女  | 大连   | 111 | 一个美女 | NULL  |

|  4 | 咚咚 | 男  | 北京   | 112 | 一个帅哥 | NULL  |

+----+------+-----+--------+-----+----------+-------+

4 rows in set

 

四、事务隔离级

1、在JDBC操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。多线程并发访问数据并且使用事务的时候,可能会遇到脏读、不可重复读、幻读。

(1)脏读(Dirty Reads):读到的线程未提交的数据。

(2)不可重复读(Non-repeatable Reads):在一个事务中读取同一个记录两次,获取数据不同。

(3)幻读(Phantom Reads):在一个事务中,读取到的记录数不同。

2、解决方案

为了避免上面出现的几种情况,在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同。

(1)       序列化(Serializable):如果隔离级为序列化,用户之间通过一个接一个顺序地执行当前的事务提供了事务之间最大限度的隔离。

(2)       可重复读取(Repeatable Read):在这一级上,事务不会被看成是一个序列。禁止不可重复读取和脏读取,但是有时可能出现幻影数据。这可以通过“共享读锁”和“排他写锁”实现。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。

(3)       读提交(Read Committed):允许不可重复读取,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。

(4)       未提交(Read Uncommitted):允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个数据则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。

第一个控制窗口

select @@tx_isolation;//查看系统环境变量

set transaction isolation level read uncommitted;

select id,name from student;//查看学生表

set @@autocommit=0;

commit;

select id,name from student;

 

第二个控制窗口

set transaction isolation level serilizable;//设置可串行化

select id,name from student;

update student

->set name='sss'

->where id=2;

select id,name from student;

set @@autocommit=0;