MySQL事务相关概念

事务是逻辑上的一组操作,要么都执行,要么都不执行。

数据库事务可以保证多个对数据库的操作(也就是 SQL 语句)构成一个逻辑上的整体。构成这个逻辑上的整体的这些数据库操作遵循:要么全部执行成功,要么全部不执行 。

1. 事务的四大特性

  1. 原子性(Atomicity):事务是最小的执行单位,不允许分割,要么全部执行,要么全部不执行。
  2. 一致性(Consistency):执行事务前后,数据保持一致,多个事务读取的结果是相同的。比如两个人进行转账,两个的总金额是1000,不过他们进行了多少次转账(事务),两个人的总额1000是不变的,这就是一致性状态。
  3. 隔离性(Isolation):并发访问数据时,一个用户事务不会被其他事务所干扰。比如有两个线程A和B对同一数据S进行事务执行,线程A在获取数据S时,线程B的事务要么已经提交结束,要么还未执行。
  4. 持久性(Durability):事务完成以后,该事务对数据库所做的更改便持久的保存在数据库之中,并不会被回滚。

2. MySQL如何保证实现四大特性

  • 保证原子性:利用innodb的undo log,undo log名为回滚日志,是实现原子性的关键,当事务执行失败或者调用rollback后,导致事务需要回滚,便可以利用undo log中的日志信息将数据恢复到修改前的样子。
  • 保证一致性:数据库通过原子性、隔离性和持久性来保证一致性,也就是说四大特性中,一致性是目的,原子性、隔离性、持久性都是手段。
  • 保证持久性:利用innodb中的redo log,当对数据做修改的时候,不仅在内存中操作,还在redo log 中记录这次操作,把redo日志从redo log buffer里刷入到磁盘文件里去,当数据库重启后,将redo log 中的内容恢复到数据库中。
  • 保证隔离性:利用锁和MVCC机制。

3. 并发事务带来的问题

  • 脏读:当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。
  • 不可重复读:是指在数据库访问中,一个事务内两次读到的数据是不一样的情况。在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。不可重复读的重点是修改。
  • 幻读就是同样的条件, 第1次和第2次读出来的记录数不一样,幻读的重点在于新增或者删除 发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
  • 丢失修改:指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。

不可重复读和幻读有什么区别呢?

  • 不可重复读的重点是内容修改或者记录减少比如多次读取一条记录发现其中某些记录的值被修改;
  • 幻读的重点在于记录新增比如多次执行同一条查询语句时,发现查到的记录增加了。

4. 事务的隔离级别


1. SQL标准定义了四个隔离级别

  • Read uncommitted 读取未提交:事务B可以读取事务A正在修改尚未提交的数据。但是会出现A事务如果回滚,这样前后数据不一致,可能出现脏读。
  • Read committed 读取已提交:A事务只能读取B事务已经提交了的数据。事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变,避免了脏读,但是可能会造成不可重复读。
  • Repeatable read 可重复读: 在事务执行期间会锁定该事务以任何方式引用的所有行,因此同一个事务发出多次select,产生的结果是相同的。避免了脏读、不可重复读,但还有可能出现幻读。注:MySQL的默认隔离级别就是Repeatable read。
  • Serializable 可串行化:Serializable是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,读锁和写锁都是排它锁,不仅可以避免脏读、不可重复读,还避免了幻读。

Mysql中使用的InnoDB存储引擎的默认隔离级别是Repeatable read 可重复读,已经可以达到可串行化的级别。

使用的的一种叫MVCC的控制方式解决不可重复读的问题 ,即Mutil-Version Concurrency Control,多版本并发控制,类似于乐观锁的一种实现方式。

2. MySQL 的隔离级别是基于锁实现的吗?
MySQL 的隔离级别基于锁和 MVCC 机制共同实现的。

SERIALIZABLE 隔离级别,是通过锁来实现的。除了 SERIALIZABLE 隔离级别,其他的隔离级别都是基于 MVCC 实现。

不过, SERIALIZABLE 之外的其他隔离级别可能也需要用到锁机制,就比如 REPEATABLE-READ 在当前读情况下需要使用加锁读来保证不会出现幻读。

3. 使用间隙锁解决幻读的问题
InnoDB采用Next-key Lock(临键锁)来避免“幻读”问题。

Record Lock:单个行记录的锁,记录锁锁定的是记录行

GAP Lock:间隙锁,锁定记录行之间的间隙范围,但不包含记录本身。

Next-Key Lock:Gap Lock+Record Lock 锁定一个范围并锁定记录本身,也就是前两者的和,锁定的区间是左开右闭的。

这样,当执行 select*from t where d=5 for update 的时候,就不止是给数据库中已有的6个记录加上了行锁,还同时加了7个间隙锁。这样就确保了无法再插入新的记录。

也就是说这时候,在一行行扫描的过程中,不仅将给行加上了行锁,还给行两边的空隙,也加上了间隙锁。

4. MVCC 的理解
MVCC(Multi-Version Concurrency Control)多版本并发控制,是用来在数据库中控制并发的方法,实现对数据库的并发访问用的。其特点就是在同一时间,不同事务可以读取到不同版本的数据,从而去解决脏读和不可重复读的问题。

实现原理:MVCC机制的实现就是通过read-view机制与undo日志,使得不同的事务会根据数据版本链对比规则读取同一条数据在版本链上的不同版本数据。通过保存数据在某个时间点的快照来实现,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值