InnoDB是如何实现事务和并发控制的?(共享锁,排它锁,行锁,表锁,MVCC,回滚)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fanxing1964/article/details/82252774

    当多个请求同时请求数据库时,如果不进行并发控制,会导致数据不一致,InnoDB保证数据一致性的方式有以下两种:

  1. 数据多版本控制

一,使用锁控制

悲观锁:就是每次拿数据都会认为别的事务也会拿数据,拿来数据就先上锁,这样别的线程拿数据就会阻塞。像行锁,页锁,表锁以及共享锁,排它锁都是悲观锁。我们说的那些锁一般都是悲观锁。

乐观锁:就是没有锁,默认其他线程不会改变数据,所以不加锁,只是在提交的时候判断是不是被更改过了,一般用版本戳实现。

按照锁的模式分为共享锁和排它锁

共享锁(Share Locks,S锁):一个线程给数据加上共享锁后,其他线程只能读取数据,不能修改。

排它锁(eXclusive Locks,X锁):一个线程给数据加上排它锁后,其他线程不能读取也不能修改。

兼容性规则为:共享锁和共享锁兼容,排它锁和其他的锁都排斥。

    如果一个请求的锁模式与当前的锁兼容,InnoDB就将请求授予该事务,反之,如果两者不兼容,该事物就会等到锁释放。

    对于update,delete和insert语句,InnoDB会自动给涉及的数据加排它锁;

    对于普通的select语句,InnoDB不会加任何锁;

事务也可以通过以下语句显示的给事务加共享锁和排它锁:

    select * from table_name where  ... lock in share mode 会给事务加上共享锁;

    select * from table_name where ... for update 会给事务加上排它锁。

按照锁的类型分为行锁和表锁以及页锁

行锁是通过给索引上的索引项加锁来实现的,只有通过索引条件来检索数据才会用到行锁,否则InnoDB将会使用表锁。

行锁:select * from table_name where  id = 1 for update 。id 字段为唯一索引字段,所以使用的就是行锁,且是排它锁。

表锁:select * from table_nane where name = ‘小巷’ for update 。name字段不是唯一索引字段,所以是表锁。

页锁:行锁锁行,表锁锁表,页锁折中,锁相邻的一组数据。

通过加锁控制,可以保证数据的一致性,但是同样一条数据,不论用什么样的锁,只可以并发读,并不可以读写并发,这时就要引入数据多版本控制了。

二,使用数据多版本(MVCC)控制

    使用锁控制并发时,只要是写数据的任务没有完成,数据就不可以被其他的任务获取,就连读数据的select操作也会阻塞,这对并发度要求较大的环境有很大的影响,为了解决这个问题引出了数据多版本。

数据多版本实现的原理是:

1,写任务发生时,首先复制一份旧数据,以版本号区分

2,写任务操作新克隆的数据,直至提交

3,并发读的任务可以继续从旧数据(快照)读取数据,不至于堵塞

  • 排它锁 是 串行执行
  • 共享锁 是 读读并发
  • 数据多版本 是 读写并发

三,redo,undo,回滚段

在InnoDB的具体实现上,依赖redo日志,undo日志,回滚段(rollback segment)

redo日志的作用?

    数据库事务提交后,按照随机方式写入磁盘上性能太低,为了提高效率先写到redo日志里,再刷到磁盘上(此时变成了顺序写)。

假如我在提交事务时数据库崩溃了,重启时,会从redo日志里把没有刷到磁盘的数据刷到磁盘上。

    简言之,redo的作用是为了保障已提交事务的ACID特性

undo日志的作用?

    数据库修改数据但未提交时,会将事务修改数据的镜像(即旧数据)存到undo日志里,当事务回滚或数据库崩溃时,会从undo日志里获取旧数据,避免未提交数据对数据库的影响。

    简言之,undo的作用是为了保障未提交的事务不会对数据库的ACID产生影响

回滚段的作用?

    存储undu日志的地方,就是回滚段。

  1. 快照读不加锁
  2. InnoDB所有的普通select都是快照读,所以可并发

https://blog.csdn.net/xiangwanpeng/article/details/55106732

https://blog.csdn.net/tanga842428/article/details/52748531

https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651961444&idx=1&sn=830a93eb74ca484cbcedb06e485f611e&chksm=bd2d0db88a5a84ae5865cd05f8c7899153d16ec7e7976f06033f4fbfbecc2fdee6e8b89bb17b&scene=21#wechat_redirect

猜你喜欢

转载自blog.csdn.net/fanxing1964/article/details/82252774