什么是事务
银行转账!张三转10000块到李四的账户,这其实需要两条SQL语句:
- 给张三的账户减去10000元;
- 给李四的账户加上10000元。
如果在第一条SQL语句执行成功后,在执行第二条SQL语句之前,程序被中断了(可能是抛出了某个异常,也可能是其他什么原因),那么李四的账户没有加上10000元,而张三却减去了10000元。这肯定是不行的!
你现在可能已经知道什么是事务了吧!事务中的多个操作,要么完全成功,要么完全失败!不可能存在成功一半的情况!也就是说给张三的账户减去10000元如果成功了,那么给李四的账户加上10000元的操作也必须是成功的;否则给张三减去10000元,以及给李四加上10000元都是失败的!
事务四大特性
一般来说,事务是必须满足4个条件(ACID)
- 原子性(Atomicity,或称不可分割性): 事务中所有操作是不可再分割的原子单位。事务中所有操作要么全部执行成功,要么全部执行失败。
- 一致性(Consistency): 事务执行后,数据库状态与其它业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。
- 隔离性(Isolation,又称独立性): 数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
- 持久性(Durability):一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。
MySQL中的事务
事务控制语句
在默认情况下,MySQL每执行一条SQL语句,都是一个单独的事务。如果需要在一个事务中包含多条SQL语句,那么需要开启事务和结束事务。
- 开启事务:start transaction;
- 结束事务:commit 或 rollback。
JDBC事务
在jdbc中处理事务,都是通过
Connection
完成的!
同一事务中所有的操作,都在使用同一个Connection对象!
Connection的三个方法与事务相关:
setAutoCommit(boolean)
:设置是否为自动提交事务,如果true(默认值就是true)表示自动提交,也就是每条执行的SQL语句都是一个单独的事务,如果设置false,那么就相当于开启了事务了;con.setAutoCommit(false)表示开启事务!!!commit()
:提交结束事务;con.commit();表示提交事务rollback()
:回滚结束事务。con.rollback();表示回滚事务
jdbc处理事务的代码格式:
try {
con.setAutoCommit(false);//开启事务…
….
…
con.commit();//try的最后提交事务
} catch() {
con.rollback();//回滚事务
}
事务隔离级别
事务的并发读问题
- 脏读 :读取到另一个事务未提交数据,即读取到了脏数据;
- 不可重复读:对同一记录的两次读取不一致,因为另一事务对该记录做了修改;
- 幻读(虚读):对同一张表的两次查询不一致,因为另一事务插入了一条记录。
四大隔离级别
4个等级的事务隔离级别,在相同数据环境下,使用相同的输入,执行相同的工作,根据不同的隔离级别,可以导致不同的结果。不同事务隔离级别能够解决的数据并发问题的能力是不同的。
1、SERIALIZABLE(串行化)
- 不会出现任何并发问题,因为它是对同一数据的访问是串行的,非并发访问的;
- 性能最差;
2、REPEATABLE READ (可重复读)(MySQL)
- 防止脏读和不可重复读,不能处理幻读问题;
- 性能比SERIALIZABLE好
3、READ COMMITTED (读已提交数据)(Oracle)
- 防止脏读,没有处理不可重复读,也没有处理幻读;
- 性能比REPEATABLE READ好
4、READ UNCOMMITTED (读未提交数据)
- 可能出现任何事务并发问题
- 性能最好
MySQL的默认隔离级别为REPEATABLE READ
可以通过下面语句查看:
select @@tx_isolation
通过下面语句来设置当前连接的隔离级别:
set transaction isolationlevel [4选1]
JDBC设置隔离级别
con. setTransactionIsolation(int level)
参数可选值如下:
- Connection.TRANSACTION_READ_UNCOMMITTED;
- Connection.TRANSACTION_READ_COMMITTED;
- Connection.TRANSACTION_REPEATABLE_READ;
- Connection.TRANSACTION_SERIALIZABLE。