事务管理:
事务的4大特性:简称acid
1.原子性(atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚
比如:
以银行转账为例,一次转账包含两个update更新语句
update t_balance set 余额=余额-1000 where card_id='11111';
update t_balance set 余额=余额+1000 where card_id='22222';
2.一致性(consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性的状态
也就是说一个事务执行之前和执行之后必须处于一致状态
比如:
以银行转账为例,转账前两个账户金额和为20000,转账后金额的和还是20000
无论怎么转账,前后的总和必须一致
3.隔离性(Isolation)
隔离性是当前多个用户并发访问数据库的时候,数据库为每一个用户开启事务
其中的某一个事务不能被其他事务操作所干扰,多个并发事务之间要相互隔离
即要达到这么一个效果:对于任意两个并发的事务T1和T2,在事务T1看来,
T2要么在T1开始之前就已经结束,要么在T1结束之后才开始执行
4.持久性(Durability)
持久性是指一个事务一旦提交了,那么对数据库中的数据的改变就是永久性的
即便是在数据库系统中遇到故障的情况下也不会丢失提交事务的操作
数据库的四种隔离级别:
1.Serializable(串行化):可以避免脏读,不可重复读,幻读的发生
2.repeatable read(可重复读):可避免脏读,不可重复读的发生
3.read committed(读已提交):可避免脏读的发生
4.read uncommitted(读未提交):最低的级别,任何情况下都可能出问题
以上四种隔离级别最高serializable,最低的read uncommitted,
隔离级别越高,执行效率就低
mysql的默认隔离级别repeatable read 可重复读
oracle数据库只支持串行化级别和读已提交两种级别,默认的是读已提交级别
因为有了并发事务,多个事务同时执行,根据数据库的隔离级别,
就会产生如下问题
1.脏读:指在一个事务处理过程中读取另一个未提交的事务中的数据
比如:以银行转账为例:
update t_balance set 余额=余额-1000 where card_id='11111';
update t_balance set 余额=余额+1000 where card_id='22222';
如果发生了这样的情况就脏读
在执行完第一个更新语句的时候,但是还没有执行第二个更新语句
另一个事务中读取t_balance表的数据,余额被减,通知用户余额减过了
还没有执行第二条更新语句就回滚了,此时已经提示过余额减过了
2.不可重复读:针对数据库中某个数据,一个事务范围内多次查询却返回不同
的数据值,这是由于在查询的间隔,被另外一个事务把数据修改并提交了
比如:
事务T1在读取某一个数据,而事务T2修改了这个数据,并且提交了事务,
事务T1再次读取这个数据,就与上一次T1事务读取值的不同,发生不可重复读
不可重复读和脏读的区别:
脏读是某一个事务读取了另一个事务未提交的脏数据,
不可重复读则是读取了上一个事务提交的数据
注意:在某些情况下,不可重复读不是问题,无论数据被改了多少次且提交
只需要获得最后提交的数据即可
幻读:事务非独立执行时发生的一种现象
比如:
事务T1对一个表中的所有的行的某个数据项做了从"1"修改数据"2"的操作
这时事务T2又对这个表添加一行数据,而这行中指定的列的数据项是"1",
并且提交给数据库,这时操作事务T1的用户查询此数据表,就会发现有一行
没有从"1"修改到"2",此种情况就是幻读
幻读和不可重复读都是读取了另一个已经提交的事务
脏读是读取的另一个未提交的事务数据
不可重复读查询的都是同一个数据项
而幻读针对是一批数据的整体中的某个数据项
在mysql中如何设置隔离级别
1.在mysql中设置
在mysql的黑白界面中
set tx_isolation='隔离级别名称'
2.在java代码中设置
Connection con=null;
try{
con=CommonDao.getConnection();
//设置数据库的隔离级别,只对当前连接有效
con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
con.setAutoCommit(false);开始事务
...
con.commit();
}catch(Excetption e){
con.rollback()
e.printStaceTrace();
}