1.事务具有ACID四个特性:
1)原子性(Atomicity):事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
2)一致性(Consistency):事务在完成后数据的完整性必须保持一致
3)隔离性(Isolation):多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间的数据要相互隔离
4)持久性(Durability):一个事务一旦被提交,它对数据库中数据的改变应该是永久性的,即使数据库发生故障也不应该对其有任何影响
如果整个事务执行过程中,有任何一个地方出现异常/错误,那么都会进行事务回滚,回滚之后数据的状态将和事务执行之前完全一致。
2.事务的并发问题
首先要知道,只有存在并发数据访问时才需要事务(提交/回滚就结束事务),当多个事务访问同一数据时,可能会存在5类并发问题,
- 3 类数据读取问题( 脏读、不可重复读和幻读)
- 2类数据更新问题(第1 类丢失更新和第2 类丢失更新)
三类数据读取问题:
1)脏读(Dirty Read): 一个事务读到了另一个事务的还没有提交数据. (比如A事务读取B事务尚未提交的数据并在此基础上操作,而B事务执行回滚,那么A 读取到的数据就是脏数据。)(很严重的行为,必须处理,不然可能有很大的影响,比如转账事务)
2)不可重复读(Unrepeatable Read): 一个事务中多次读到的数据不一致,一个事务读到了另一个事务修改后的数据。(不可重复读,保证数据修改后,不会出现两次一样的数据)
3) 幻读(虚读Phantom Read):一个事务读到了另一个事务insert提交的数据。(比如事务A 重新执行一个查询,返回一系列符合查询条件的行,发现其中插入了被事务B 提交的行)(不可能出现在MySQL中,只会出现在Oracle中)
两类丢失更新问题
1)第一类丢失更新:
事务A撤销时, 把已经提交的事务B的更新数据覆盖了
2)第二类丢失更新:
事务A覆盖事务 已经提交的数据,造成事务B 所做的操作丢失
3.事务的隔离级别:
数据库为用户提供了自动锁机制,只要用户指定会话的事务隔离级别, 数据库就会通过分析SQL语句然后为事务访问的资源加上合适的锁。
隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义有五个表示隔离级别的常量(用于解决并发问题)一般情况下使用中间两种就行。
TransactionDefinition 接口事务隔离级别 | 描述 |
---|---|
Read uncommitted(读未提交) | 就是一个事务可以读取另一个未提交事务的数据。该级别不能防止 脏读,不可重复读和幻读,因此很少使用该隔离级别。 |
Read committed(读提交) | 就是一个事务要等另一个事务提交后才能读取数据。系统默认值,可以防止脏读但不能防止不可重复读和幻读,是大多数情况下的推荐值 |
Repeatable read(重复读) | 该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。 |
Serializable (序列化) | 所有的事务依次逐个执行,事务之间就完全不可能产生干扰。该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。 |
事务隔离级别和数据访问的并发性是对立的,事务隔离级别越高并发性就越差。所以要根据具体的应用来确定合适的事务隔离级别,这个地方没有万能的原则。
4.JDBC如何进行事务处理:
- Connection提供了事务处理的方法,通过调用setAutoCommit(false)可以设置手动提交事务。
- 当事务完成后用commit()显式提交事务;
- 如果在事务处理过程中发生异常则通过rollback()进行事务回滚。
- 除此之外, 从JDBC 3.0 中还引入了Savepoint( 保存点)的概念,允许通过代码设置保存点并让事务回滚到指定的保存点。