首页 > 代码库 > 数据库的隔离级别
数据库的隔离级别
一、数据库是什么?
数据库(Database)是按照数据结构来组织、存储和管理数据的建立在计算机存储设备上的仓库。
二、为什么会需要隔离机制?
通过数据库定义的理解,换句话说就是,数据是以一种文件的形式存储在物理结构上的。
而对于文件的操作就是IO流的操作,即读与写的操作。
而对于我们平常的数据操作,不管多么复杂的业务,都是select和insert/update/delete。
我们再试想一下,如果在多线程高并发下读写操作又会出现什么情况?
如果不做任何的处理,是不是就会出现数据处理错误。也是我们所说的,脏读或幻读。
对于这种情况,JAVA中通常的做法就是加锁。对应于数据库就是排它锁、共享锁等。
那加锁又是怎么处理的呢?
加锁首先应该明确是的,什么时候加锁?对什么加锁?
当多个线程都操作同一数据的时候,我们是不是就应该加锁。
而数据库的隔离机制也就是数据操作的锁机制。当然数据库的机制远比这个要复杂,只是想让大家明白,一切的 重心都是数据,不要被各种术语而弄懵逼了。
三、数据库共有四种隔离级别:
Read Uncommitted(读取未提交内容)
Read Committed(读取提交内容)
Repeatable Read(可重读)
Serializable(可串行化)
四种隔离级别详解:
1、Read Uncommitted(读取未提交内容)
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
2、Read Committed(读取提交内容)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
3、Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
4、Serializable(可串行化)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
一旦读取数据,则就对事张表加锁。只允许其他事务读取数据,不能进行修改和新增数据操作。必须等待当前事务结束。
四、事务的4大特性
4.1、原子性(Atomicity):事务是数据库的逻辑工作单位,它对数据库的修改要么全部执行,要么全部不执行。
4.2、一致性(Consistemcy):事务前后,数据库的状态都满足所有的完整性约束。
4.3、隔离性(Isolation):并发执行的N个事务是隔离的,一个不影响一个,一个事务在没有commit之前,被修改的数据不可能被其他事务看到(通过设置数据库的隔离级别)。
4.4、持久性(Durability):持久性意味着当系统或介质发生故障时,确保已提交事务的更新不能丢失。持久性主要在于DBMS的恢复性能。
五、脏读、不可重复读、幻读
5.1 脏读、不可重复读、幻读都是对数据操作时的体现。
5.2 脏读、不可重复读、幻读都是事务有关,也就是在并发执行时发生的情况。
5.3 脏读:
脏读又称无效数据读出。一个事务读取另外一个事务还没有提交的数据叫脏读。
例如:事务T1修改了一行数据,但是还没有提交,这时候事务T2读取了被事务T1修改后的数据,之后事务T1因 为某种原因Rollback了,那么事务T2读取的数据就是脏的。
解决办法:把数据库的事务隔离级别调整到READ_COMMITTED
5.4 不可重复读:
不可重复读是指在同一个事务内,两个相同的查询返回了不同的结果。
例如:事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得 到了不同的结果。
解决办法:把数据库的事务隔离级别调整到REPEATABLE_READ
5.5 幻读:
例如:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插 入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一 样。这就叫幻读。
解决办法:把数据库的事务隔离级别调整到SERIALIZABLE_READ
数据库的隔离级别