为什么会有事务隔离:
数据库是给广大用户共享的,必然会存在并发读写操作,那么可能出现以下现象:
1、更新丢失
比如两个事务都同时更新同一行数据,一个事务对数据的更新把另一个事务对数据的更新覆盖了,这个因为系统没有执行任何的锁操作,
因此并发事务并没有被隔离开来。
eg:
比如一个价格是2,两个事务同时对这个价格做更新,事务A给价格加8,事务b给价格加5,按照操作的意愿价格应该是15。
但是如果:
a、事务A先提交,那么结果就是:7
b、事务B先提交,那么结果就是:10
2、脏读
一个事务读取到了另一个事务未提交的数据操作结果。(要是所有的操作都被回滚了呢???)
eg:
比如一个价格是4,事务A修改这个价格为:9但是事务还未被提交,而这时候事务B读取了这个由未提交事务A的跟新价格:9
如果这个时候事务A被rollback回滚了,那么事务B读取到的数据就不正确的,就是脏读。
3、不可重复度(顾名思义就是多次读取的数据不一致)
一个事务对同一行数据重复读取两次,但是却得到了不同的结果。
这个不同的结果有两种情况:
A、某一行的数据被更新过
B、数据表有新插入的行或者被删除的行
根据不同的结果不可重复度又可以分两种:
虚读:事务T1读取某一数据后,事务T2对其做了修改,当事务T1再次读取时得到与前一次不同的值。
幻读:由于两次查询过程中有另外一个事务插入或删除数据造成第二次查询的结果相对第一次查询结果会出现未出现的数据或缺少的数据。
区别于脏读:
脏读是不正确,幻读或虚读是不一致
如何解决上面出现的现象:
那就是对事务进行限制:事务隔离级别 (Mysql支持的是行锁) (要是范围区间呢???)
READ UNCOMMITED:(未提交读:顾名思义就是未提交的事务操作结果也可以读)
在READ UNCOMMITTED这个级别,事务中的修改,即使没有提交,对其他事务也都是可见的。
事务可以读取未提交的数据。(如果事务被回滚那出现‘脏读’)这个级别会导致很多问题 ,在实际
应用很多使用。
READ COMMITTED:(读提交:顾名思义就是提交了的事务操作结果才能读)
READ COMMITED这个级别:一个事务的开始时,只能‘看见’已经提交的事务所做的操作。也就是说
一个事务从开始到提交之前,所做的任何修改对其他事务都是不可见的。既然这样那么这个事务开始前和提交后
的结果不同,那么另一个事务多次读取的话就出现数据不一致(不可重复读)。
REPEATABLE READ:(可重复度:顾名思义就是一个事务多次读取数据都一致)
REPEATABLE READ这个级别是Mysql数据库的默认级别。这个级别保证在同一个事务的多个实例在并发读取
数据时,会看到同样的数据行。
针对某一
行
的话:读取数据的事务将会禁止写事务(但允许读事务),写事务则
禁止任何其他事务。
但如果查询的是
范围区间
: 那么其他事务在这个范围内插入新行,然后再次查询就出现‘幻行’。
InnoDB引擎通过MVCC多版本并发控制解决幻读的问题。
SERIALIZABLE:(serializable可串行化)
SERIALIZABLE是最高的隔离级别。通过强制事务串行执行(强制事务排序,使之不可能相互冲突),事务只能一个接着一个地执行,
但不能并发执行。
,避免幻读。
SERIALIZABLE会在读取的每一行数据上都
加锁,如果仅仅通过“行级锁”是无法实现事务序列化的,必须
通过其他机制保证
新插入的数据不会被刚执行查询操作的事务访问到。所以可能导致大量的超时和锁争用的问题。实际应用很少用到这个级别。
离级别 | 脏读(Dirty Read) | 不可重复读(NonRepeatable Read) | 幻读(Phantom Read) |
读未提交(Read uncommitted) | 可能 | 可能 | 可能 |
读已提交(Read committed) | 不可能 | 可能 | 可能 |
可重复读(Repeatable read) | 不可能 | 不可能 | 可能 |
可串行化(Serializable ) | 不可能 | 不可能 | 不可能 |
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed。它能够避免脏读取,而且具有较好的并发性能。
尽管它会导致
不可重复读
、幻读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用
悲观锁
或
乐观锁
来控制。
查看InnoDB系统级别的事务隔离级别:
select @@global.tx_isolation;
查看InnoDB会话级别的事务隔离级别:
select @@tx_isolation;
修改事务隔离级别:
系统级别: set global transaction isolation level read committed;
会话级别:set session transaction isolation level read committed;
InnoDB的可重复读隔离级别和其他数据库的可重复读是有区别的,不会造成幻象读(phantom read),
所谓幻象读,就是同一个事务内,多次select,可以读取到其他session insert并已经commit的数据。
既然是测试事务而且还是可重复读隔离级别:
那么就要开启事务为手动提交事务模式,设置autocommit为0。(session级别)
设置隔离级别为:repeatable read。(seesion级别)
所操作的数据表的引擎要为:InnoDB。
==============================================================================================================
无法与MyISAM引擎来做个对比,因为MyISAM不支持事务。
实验证明:
InnoDB的可重复读隔离级别是不会出现幻读的。
PS:编辑觉得没有有道云笔记方便