1、 概念
事务指的是逻辑上的一组操作,这组操作要么全部成功,要么全部失败!
2、特性
- 原子性(Atomicity):是指事务中的操作要么全部成功,要么全部失败。
- 一致性(Consistency):意思是事务必须使数据库从一个一致性状态变换到另外一个一致性状态。例:A向B转账,转账之前,两个人的钱总和是2000,A向B转账之后,无论怎么转,两个人的钱总和还是2000,这就是所谓的事务的一致性。(前提是没有第三者的参与)
- 隔离性(Isolation):在多用户并发访问数据库的时候,数据库为每一个用户开启的事务,不会被其他事务的操作影响。例:A用户在消费,B用户也在消费,但是两个人之间的消费并不会相互影响。
- 持久性(Durability):事务一旦被提交,它对数据库造成的改变就是持久性的,不可改变的。例:一旦转账成功,A、B两个人的账户金额就确定下来了,不可改变。
3、 隔离级别
在介绍隔离级别之前,先介绍一下可能会出现的几种状态:
- 脏读:一个事务读取到了另一个事务未提交的数据。例:A向B转账,当B用户的钱增加时,A用户的钱在减少时出现了异常进行回滚。此时,在B用户新增之后,A用户减少之前又有另外一个线程读取到了B用户新增之后的金钱数,这就是脏读。
- 不可重复读:多个事务,其他的事务操作导致某个事务两次读取的数据不一致。例:A向B转账,当这个事务还未提交时,另一个线程读到了B的金钱为一个数,当事务提交之后,读到的数据又是另一个数,导致两次读到B的金钱不一致,这就是不可重复读。
注意:1.不可重读针对已经提交的数据。2.两次或多次读取同一条数据。 - 幻读(虚读):其他事务的数据操作导致某个事务两次读取到的数据数量不一致。例:thread1在time1时刻向数据库中插入一条数据,并在time3时刻提交;thread2在time2时刻读取到的数据库数据为N1条,在time4时刻读取的数据库数量为N2,N1 != N2,这就是幻读。
注意:1.幻读针对已经提交的数据。2.两次或多次读取不同行数据,数量上新增或减少。
针对以上情况,jdbc定义了5种事务的隔离级别:
- TRANSACTION_NONE 无事务,默认值为0,mysql不支持。
- TRANSACTION_READ_UNCOMMITTED 允许脏读,不可重读,幻读,默认值为1。
- TRANSACTION_READ_COMMITTED 直译为仅允许读取已提交的数据,即不能读脏,但是可能发生不可重读和幻读,默认值为2。
- TRANSACTION_REPEATABLE_READ 不可读脏,保证同一事务重复读取相同数据,但是可能发生幻读,默认值为4。
- TRANSACTION_SERIALIZABLE 直译为串行事务,保证不读脏,可重复读,不可幻读,事务隔离级别最高,默认值为8。
默认值我不记得对不对了,如果不对,可以指出!
在MySQL中,实现了这四种隔离级别,分别有可能产生问题如下所示:
隔离级别 | 脏读 | 不可重复读 | 幻读(虚读) |
读未提交(Read uncommitted) | √ | √ | √ |
读已提交(Read committed) | × | √ | √ |
可重复读(Repeatable read) | × | × | √ |
可串行化(Serializable) | × | × |
在SQL语句中:
strat transaction 开启事务
commit或rollback 结束事务。
Java伪代码:
Connection con = JdbcUtils.getConnection();
//手动提交
con.setAutoCommit(false);
con.commit();
//回滚事务
con.rollback();
// 设置保存点
Savepoint sp = con.setSavepoint();
// 回滚到指定保存点
con.rollback(sp);
//设置隔离级别
con.setTransactionIsolation(int level)