暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

事务的基础概念

南北技术笔记 2020-11-12
398

1.事务概念

    事务是由一系列SQL组成的逻辑处理单元,要么全部执行,要不全不执行。事务有四个属性,如下:

  • 原子性:事务是一个原子操作单元,其对数据的修改,要么全部执行,要么全不执行。

  • 一致性:在事务开始和完成时,数据都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性;事务结束时,所有的内部数据结构也都必须是正确的。

  • 隔离性:数据库系统提供一定的隔离机制,保证事务不受外部并发操作影响的“独立环境”运行。这意味着事务处理过程中的中间状态对外是不可见的。

  • 持久性:事务完成之后,它对于数据的修改是永久性的。


2.并发事务带来的问题

    事务的运行常常是并发的,因为并发的事务执行效率高于串行执行,然而并发往往会带来大量的问题。

  • 更新丢失:当多个事务同时更新同一行记录时,如果没有做限制的话,可能出现事务修改内容被覆盖(被覆盖的事务还没有提交)的情况。

  • 脏读:一个事务对数据做了修改但是事务还没有提交,这时另一个事务读取了被修改的数据,就是发生了脏读。

  • 不可重复读:一个事务读取某条数据后的某个时间,重复读取这条数据,得到了不一样的结果,这种情况叫做不可重复读。

  • 幻读:一个事务相同的范围查询查询多次,每次读取的总记录数不一样,就是发生了幻读。


3.事务的隔离级别

    “脏读”、“不可重复读”、“幻读“这些其实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。数据库实现隔离机制主要有下面两种方式:

  • 在读取数据前,对其加锁,阻止其他事务对数据进行修改。

  • 不加任何锁,通过一定机制生成一个数据请求时间点的一致性数据快照,并用这个快照提供一定级别的一致性读取。对用户来说,就好像一条数据有多个版本一样,InnoDB管这个叫做MVCC(多版本并发控制)。

   

    数据库的隔离级别越高,并发“副作用”越小,但是付出的代价也就越大。因为事务隔离的本质其实就是让事务在一定程度上“串行化”执行。下面表格是InnoDB四种隔离级别以及可能产生的“副作用”:

事务隔离级别
脏读
不可重复读
幻读
幻读
读未提交




读已提交

可重复读




串行化


 MySQL遵循的是二段锁协议,将事务分成两个阶段,加锁阶段/解锁阶段。

  1. 加锁阶段:该阶段可以加锁,对任何数据读操作以前先申请读锁(其他事务可以再申请读锁,不能申请写锁),进行写操作之前申请写锁(其他食物不能申请任何锁)。加锁不成功,事务进入等待状态,直到加锁成功,才继续执行。

  2. 事务释放了一个封锁之后,事务进入解锁阶段,该阶段只能解锁,不能加锁。


不同隔离级别加锁操作:

  • 读未提交,任何操作都不加锁。

  • 读已提交,写操作写锁维持到事务结束。判断操作是否有索引,有索引的话只锁指定的数据行(Record Lock),没有的话是表锁。但是真要是表锁的情况,MySql会做一些改进,在MySQL Server过滤条件,发现不满足后,回调用unlock_row方法把不满足条件的记录锁释放掉,可重复读级别也是如此

  • 可重复读,读锁和写锁都是维持到事务结束。判断操作是否有索引,没有索引是表锁,有索引是next key lock。

  • 串行化,任何操作都会加锁,而且都是表锁。


事务隔离需要注意的点:

  1. 事务隔离为读已提交时,写操作只会锁住对应的数据行。

  2. 隔离为可重复读时,写操作如果检索条件有索引的时候,默认加锁是next-key(record lock+gap lock),如果检索条件没有索引的情况,写操作是表锁。gap lock是为一个间隙加锁,这样的话,这个间隙就不能再插入记录了,可以防止幻读。

  3. 隔离为串行化时,读写都是表锁。


文章转载自南北技术笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论