事务的特性:
- 原子性:指处于同一个事务中的多条语句是不可分割的。
- 一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
- 隔离性:指多线程环境下,一个线程中的事务不能被其他线程中的事务打扰
- 持久性:事务一旦提交,就应该被永久保存起来。
如果不考虑事务的隔离性,会出现以下问题:
- 脏读:指一个线程中的事务读取到了另外一个线程中未提交的数据。
- 不可重复读(虚读):指一个线程中的事务读取到了另外一个线程中提交的update的数据。
- 幻读:指一个线程中的事务读取到了另外一个线程中提交的insert的数据。
- 丢失更新:撤销一个事务时,把其他事务已提交的更新数据覆盖。
隔离级别:
隔离级别 | 脏读(Dirty Read) | 不可重复读(NonRepeatable Read) | 幻读(Phantom Read) |
未提交读(Read uncommitted) | 可能 | 可能 | 可能 |
已提交读(Read committed) | 不可能 | 可能 | 可能 |
可重复读(Repeatable read) | 不可能 | 不可能 | 可能 |
可串行化(Serializable ) | 不可能 | 不可能 | 不可能 |
级别越高,数据越安全,但性能越低。
不可重复读(虚读)与幻读比较相似,都是在一个事务中多次读取到不同的数据。
- 不可重复读:即虚读,也就是大家经常说的不可重复读,是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其他事务修改的提交而引起的。比如事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。
- 一种更易理解的说法是:在一个事务内,多次读同一个数据。在这个事务还没有结束时,另 一个事务也访问该同一数据。那么,在第一个事务的两次读数据之间。由于第二个事务的修改,那么第一个事务读到的数据可能不一样,这样就发生了在一个事务内 两次读到的数据是不一样的,因此称为不可重复读,即原始读取不可重复。
- 幻读,是指事务A读取与搜索条件相匹配的若干行。事务B以插入或删除行等方式来修改事务A的结果集,然后再提交。
- 幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。
- 同时,第二个事务也 修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一 样.
- 一般解决幻读的方法是增加范围锁RangeS,锁定检锁范围为只读,这样就避免了幻读。
- 简单来说,幻读是由插入或者删除引起的。
设置隔离级别
每个数据库连接都有默认的隔离级别,通常是读已提交或可重复读.可以通
过数据库配置设置,也可在应用程序中设置.例如Hibernate:
- hibernate.connection.isolation = 4
- 1—Read uncommitted isolation
- 2—Read committed isolation
- 4—Repeatable read isolation
- 8—Serializable isolation
注意:
- Hibernate不可能改变在受管环境下由应用服务器提供的数据库连接的隔离级别,只能通过改变应用服务器配置的方式来改变.
- 设置隔离级别是全局选项,会影响所有的连接和事务.有时需要为某个特定事务指定更多的限制.
- Hibernate依赖于乐观的并发控制,使用版本检查和悲观锁实现附加的锁支持(了解).
MySQL
mysql默认的事务处理级别是'REPEATABLE-READ',也就是可重复读 1.查看当前会话隔离级别 select @@tx_isolation; 2.查看系统当前隔离级别 select @@global.tx_isolation; 3.设置当前会话隔离级别 set session transaction isolatin level repeatable read; 4.设置系统当前隔离级别 set global transaction isolation level repeatable read;
Oracle
oracle数据库支持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别。 默认系统事务隔离级别是READ COMMITTED,也就是读已提交