数据库事务初识
事务概述
一件事情有n个组成单元组成,要不这n个组成单元同时成功,要不n个单元同时失效。
MySQL的事务
- 默认的事务:一条sql语句就是一个事务。
- 手动事务:
- 显示地开启一个事务:start transaction
- 事务提交:commit代表从开启事务到事务提交,中间所有的sql语句都认为是有效的,真正的更新数据库。
- 事务的回滚:rollback 代表事务的回滚,从开启事务到事务的回滚,中间的所有操作都认为是无效的,数据库没有被更新。
注意:控制事务的conn必须是同一个。
// 通过conn对象手动开启事务
conn.setAutoCommit(false);
// 提交事务
conn.commit();
// 事务回滚
conn.rollback();
- 注意:不管在什么情况下,事务控制一般都在业务层执行。
- 所有的方法调用用的都是同一个线程。
提交代表事务结束,将Connection对象从ThreadLocal中移除。
Connection conn = getCurrentConnection();
conn.commit();
tl.remove();
conn.close();
事务的特性ACID
- 原子性(Atomictity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
- 一致性(Consistency):一个事务中,事务前后数据的完整性必须一致。
- 隔离性(Isolation):指多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离。
- 持久性(Durability):指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
并发访问问题--由隔离性引起
如果不考虑事务隔离性,事务存在3中并发访问问题
- 脏读:B事务读取到了A事务尚未提交的数据。--要求B事务要读取A事务提交的数据。
- 不可重复读:一个事务中,两次读取的数据的内容不一致。--要求一个事务中多次读取的数据应该是一致的。(update)
- 幻读/虚读:一个事务中,两次读取的数据量不一致。--要求在一个事务多次读取的数据的数量是一致的。(insert delete)
注意:脏读是最要命的。
事务的隔离级别
- read uncommitted:读取尚未提交的数据。哪个问题都不能解决
- read committed:读取已经提交的数据。可以解决脏读。(Oracle默认的)
- repeatable read:重读读取。可以解决脏读和不可重复读。(mysql默认的)
- serialiable:串行化。可解决脏读不可重复读和虚读。(相当于锁表,性能很低。不用)
总结
-
mysql的事务控制
- 开启事务:start transaction;
- 提交:commit;
- 回滚:rollback;
-
jdbc事务控制
- 开启事务:conn.setAutoCommit(false);
- 提交:conn.commit();
- 回滚:conn.rollback();
-
DBUtils的事务控制
也是通过JDBC -
ThreadLocal:实现的是通过线程绑定的方式传毒参数
-
事务的特性ACID
- 并发问题:脏读、不可重复读、虚读/幻读
- 解决并发:设置隔离级别
- read uncommitted
- read committed
- repeatable read(mysql默认)
- serializable
-
隔离级别的性能
read uncommitted > read committed > repeatable read(mysql默认)> serializable -
隔离级别的安全性
read uncommitted < read committed < repeatable read(mysql默认)< serializable