事务隔离性
当多个线程都开启事务操做数据库中数据时,数据库系统要能进行隔离操做,以保证各个线程获取数据的准确性。数据库
若是没有隔离,会发生的几种问题
脏读(Dirty Read)并发
一个事务处理过程里读取了另外一个未提交的事务中的数据性能
不可重复读(NonRepeatable Read)spa
对于数据库中的某个数据,一个事务范围内屡次查询却返回了不一样的数据值,这是因为在查询的间隔期间,另一个事务修改并提交了该数据。线程
不可重复读和脏读的区别是,脏读是某一事务读取了另外一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。blog
在某些状况下,不可重复读并非问题,好比咱们屡次查询某个数据固然以最后查询获得的结果为主。但在另外一些状况下就有可能发生问题,例如对于同一个数据A和B依次查询就可能不一样,A和B就可能打起来了……。索引
幻读(Phantom Read)事务
在一个事务中读取到了别的事务插入的数据,致使先后不一致。it
事务A 按照必定条件进行数据读取,期间事务B插入了相同搜索条件的新数据,事务A再次按照原先条件进行读取时,发现了事务B 新插入的数据。table
不一样隔离级别的问题
MySQL的锁类型
表锁
对一整张表加锁,并发能力低下(即便有分读锁、写锁),通常在DDL处理时使用,myisam也是表锁。
行锁
只锁住特定行的数据,并发能力强,MySQL通常都是用行锁来处理并发事务。
若是用到无索引的字段,那么MySQL会在存储引擎层面将全部的记录加锁,而后由MySQL Server过滤,若是不知足会调用unlock_row把不知足条件的记录释放锁(这里违背了二段锁协议)。
这种状况一样适用于MySQL的默认隔离级别RR。因此对一个数据量很大的表作批量修改的时候,若是没法使用相应的索引,MySQL Server过滤数据的的时候特别慢,就会出现虽然没有修改某些行的数据,可是它们仍是被锁住了的现象。
GAP锁(间隙锁)
MySQL使用索引对行锁两边的区间进行加锁,避免其余事务在这两个区间insert的一种锁。
如图所示:数据库中存在值5,30。那么数据库会将数据段切分如下几个区间:
(negative infinity, 5],
(5,30],
(30,positive infinity)
当对值为30这一行加行锁的时候,会同时对(5,30]和(30,positive infinity)加GAP锁。这样其余事务若是想在这两个区间进行insert操做的时候,须要等待本次事务完成。
若是对不存在的数据进行更新,好比更新20(不存在)对应数据行,那么数据库也会对其存在的区间(5,30]加GAP锁。这样,若是有其余事务想插入值为10的数据,须要等待20这个事务完成。
若是使用的是没有索引的字段,那么会给全表加入GAP锁。
Next-Key锁
Next-Key锁是行锁和GAP锁的合并(MySQL使用它来避免幻读)
MVVC(多版本并发控制)
Innodb中的乐观锁实现。经过它提升MySQL的读取操做的性能。并能解决MySQL的重复读问题。
MVVC在每一行记录的后面加两个隐含列(记录建立版本号和删除版本号)。这里的版本号指的是事务的版本号(每一个事务启动的时候,都有一个递增的版本号)。
Innodb中事务隔离级别和锁的关系
Innodb经过使用不一样的锁来实现事务隔离
避免脏读
经过对数据加行锁或则表锁,使对同一数据进行操做的事务处于等待状态,来避免同时操做
避免不可重复读
经过MVVC实现事务的可重复读
避免幻读
经过Next-Key锁避免产生幻读现象。
MySQL在RC和RR中都避免了幻读现象。
----------------------------------------------------------------------------------------------
悲观锁
乐观锁
在冲突比较少的时候采用乐观锁,减小不须要加锁释放锁的开销,能够提升性能。
在冲突比较多的时候采用悲观锁,减小重复尝试次数,乐观锁重复操做的代价比较大。