一、并发控制

 
因为并发情况下有可能出现不同线程对同一资源进行变动,所以必须要对并发进行控制以保证数据的同一与安全。
 
可以参考CPython解释器中的GIL全局解释器锁,所以说python中没有真正的多线程,多线程任意时刻只有一个程序能申请到GIL操作CPU。

 

1.2 Innodb中的并发控制

 

锁(lock)
数据多版本(multi versioning)

 

1.2.1 锁

 

  • 使用普通锁来保证数据的一致性:
     
    操作数据前实行互斥,即当前程序曹锁数据时,不允许其他并发任务操作该数据,进入排队等待
    操作完成后释放锁
     

  • 普通锁问题:
    锁定粒度大,容易出现死锁
    简单粗暴,没有并行“读任务”,本质上是串行执行任务。

  • 正对上述问题,有了共享锁及排他锁

  1. 共享锁(share locks 称为S锁)读取数据时加S锁
    共享锁之间不互斥,简记为:读读可以并行

  2. 排他锁(exclusive locks 称为X锁)修改数据时加X锁
    排他锁与任何锁互斥,简记为:写读,写写不可以并行

上述中可以了解到,只要修改数据时加了排他锁, 其它操作同一数据的并行线程都进入了排队等待释放锁。且写的数据没有完成提交的话,其它任务是没法去读取数据的,也阻塞了

 

1.2.2 数据多版本(某种意义的读写分离)

 

  • 作为一种提高并发的方式:原理
  1. 写任务发生时,将数据克隆一份,以版本号区分;

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

  3. 并发读任务可以继续读取旧版本的数据,不至于阻塞;

  • 如上图:
  1. 最开始数据的版本是V0;

  2. T1时刻发起了一个写任务,这是把数据clone了一份,进行修改,版本变为V1,但任务还未完成;

  3. T2时刻并发了一个读任务,依然可以读V0版本的数据;

  4. T3时刻又并发了一个读任务,依然不会阻塞;

可以看到,数据多版本,通过“读取旧版本数据”能够极大提高任务的并发度。

总结:

  • 普通锁,本质是串行执行

  • 读写锁,可以实现读读并发
  • 数据多版本,可以实现读写并发

 

二、Innodb redo/undo 日志、回滚段 (rollback segment) 操作,实现上述思路

 

  • ACID:
    原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)

 

2.1 redo日志

 

数据库事务提交后,必须将更新后的数据刷到磁盘上,以保证ACID特性。磁盘随机写性能较低,如果每次都刷盘,会极大影响数据库的吞吐量。

优化方式为:将修改行为先写到redo日志里(此时变成了顺序写),再定期将数据刷到磁盘上,这样能极大提高性能。

假如某一时刻,数据库崩溃,还没来得及刷盘的数据,在数据库重启后,会重做redo日志里的内容,以保证已提交事务对数据产生的影响都刷到磁盘上。

一句话,redo日志用于保障,已提交事务的ACID特性。

 

2.2 undo日志

 

数据库事务未提交时,会将事务修改数据的镜像(即修改前的旧版本)存放到undo日志里,当事务回滚时,或者数据库奔溃时,可以利用undo日志,即旧版本数据,撤销未提交事务对数据库产生的影响。

对于insert操作,undo日志记录新数据的PK(ROW_ID),回滚时直接删除;

对于delete/update操作,undo日志记录旧数据row,回滚时直接恢复;

他们分别存放在不同的buffer里。

一句话,undo日志用于保障,未提交事务不会对数据库的ACID特性产生影响。

 

2.3 回滚段

 

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

undo日志和回滚段和InnoDB的MVCC密切相关

建议看完MVCC原理再看下面:MVCC原理
直接看也行

举例:
create table tb(
id int auto_increment primary key,
name cahr(32));

插入三条数据
1, shenjian

2, zhangsan

3, lisi

此时没有事务未提交,故回滚段是空的。

接着启动了一个事务:

start trx;

delete (1, shenjian);

update set(3, lisi) to (3, xxx);

insert (4, wangwu);

并且事务处于未提交的状态。

可以看到:

(1)被删除前的(1, shenjian)作为旧版本数据,进入了回滚段;

(2)被修改前的(3, lisi)作为旧版本数据,进入了回滚段;

(3)被插入的数据,PK(4)进入了回滚段;

接下来,假如事务rollback,此时可以通过回滚段里的undo日志回滚。

假设事务提交,回滚段里的undo日志可以删除。

可以看到:

(1)被删除的旧数据恢复了;

(2)被修改的旧数据也恢复了;

(3)被插入的数据,删除了;

事务回滚成功,一切如故。

 

三、innodb 是基于MVCC(多版本并发控制)的存储引擎

 
InnoDB是高并发互联网场景最为推荐的存储引擎,根本原因,就是其多版本并发控制(Multi Version Concurrency Control, MVCC)。行锁,并发,事务回滚等多种特性都和MVCC相关。

MVCC就是通过“读取旧版本数据”来降低并发事务的锁冲突,提高任务的并发度。

旧数据存储的地方:
(1)旧版本数据存储在回滚段里;

(2)对MySQL和InnoDB原有架构体系冲击不大;

InnoDB的内核,会对所有row数据增加三个内部属性:

(1)DB_TRX_ID,6字节,记录每一行最近一次修改它的事务ID;

(2)DB_ROLL_PTR,7字节,记录指向回滚段undo日志的指针;

(3)DB_ROW_ID,6字节,单调递增的行ID;

回滚段里的数据,其实是历史数据的快照(snapshot),这些数据是不会被修改,select可以肆无忌惮的并发读取他们。

快照读(Snapshot Read),这种一致性不加锁的读(Consistent Nonlocking Read),就是InnoDB并发如此之高的核心原因之一。

这里的一致性是指,事务读取到的数据,要么是事务开始前就已经存在的数据(当然,是其他已提交事务产生的),要么是事务自身插入或者修改的数据。

什么样的select是快照读?

除非显示加锁,普通的select语句都是快照读,例如:

select * from t where id>2;

这里的显示加锁,非快照读是指:

select * from t where id>2 lock in share mode;

select * from t where id>2 for update;

总结

(1)常见并发控制保证数据一致性的方法有锁,数据多版本;

(2)普通锁串行,读写锁读读并行,数据多版本读写并行;

(3)redo日志保证已提交事务的ACID特性,设计思路是,通过顺序写替代随机写,提高并发;

(4)undo日志用来回滚未提交的事务,它存储在回滚段里;

(5)InnoDB是基于MVCC的存储引擎,它利用了存储在回滚段里的undo日志,即数据的旧版本,提高并发;

(6)InnoDB之所以并发高,快照读不加锁;

(7)InnoDB所有普通select都是快照读;

Innodb 实现高并发、redo/undo MVCC原理的更多相关文章

  1. MySQL InnoDB 实现高并发原理

    MySQL 原理篇 MySQL 索引机制 MySQL 体系结构及存储引擎 MySQL 语句执行过程详解 MySQL 执行计划详解 MySQL InnoDB 缓冲池 MySQL InnoDB 事务 My ...

  2. InnoDB高并发原理

    一.并发控制 为啥要进行并发控制? 并发的任务对同一个临界资源进行操作,如果不采取措施,可能导致不一致,故必须进行并发控制(Concurrency Control). 技术上,通常如何进行并发控制? ...

  3. (转载)java高并发:CAS无锁原理及广泛应用

    java高并发:CAS无锁原理及广泛应用   版权声明:本文为博主原创文章,未经博主允许不得转载,转载请注明出处. 博主博客地址是 http://blog.csdn.net/liubenlong007 ...

  4. 《Netty Zookeeper Redis 高并发实战》 图书简介

    <Netty Zookeeper Redis 高并发实战> 图书简介 本书为 高并发社群 -- 疯狂创客圈 倾力编著, 高度剖析底层原理,深度解读面试难题 疯狂创客圈 Java 高并发[ ...

  5. 尼恩 Java高并发三部曲 [官方]

    高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三部曲 > 面试必备 + 大厂必备 + 涨薪 ...

  6. SpringCloud、Nginx高并发核心编程 【2020年11月新书 】

    文章太长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典极品 : 三大本< Java 高并发 三部曲 > 面试 + 大厂 + 涨薪必备 疯狂创客圈 经 ...

  7. InnoDB事务日志(redo log 和 undo log)详解

    数据库通常借助日志来实现事务,常见的有undo log.redo log,undo/redo log都能保证事务特性,undolog实现事务原子性,redolog实现事务的持久性. 为了最大程度避免数 ...

  8. Mysql 中的MVCC原理,undo日志的依赖

    一. MVCC 原理了解   原文点击:MVCC原理浅析 读锁: 也叫共享锁.S锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的 ...

  9. MVCC原理 4步 什么是MVCC、事务ACID、事物隔离级别、Innodb存储引擎是如何实现MVCC的

    MVCC是来处理并发的问题,提高并发的访问效率,读不阻塞写.事物A 原子性C 一致性I 隔离性D 持久性高并发的场景下的问题脏读不可重复读幻读事物隔离级别RU读未提交 脏读/不可重复读/幻读 .不适用 ...

随机推荐

  1. python根据关键字以及id值爬取图虫网上高质量大图

    import requests import re import os import time print("ready....") def downPic(dirs, keywo ...

  2. win10同时安装 office2016和visio2016

    一.下载镜像文件 因为office 2016和 visio2016 镜像文件是一样的,只是名称不一样,所以只需要下载一个即可. 二.下载Office 2016 Deployment Tool工具 到微 ...

  3. AI学习---分类算法[K-近邻 + 朴素贝叶斯 + 决策树 + 随机森林 ]

    分类算法:对目标值进行分类的算法    1.sklearn转换器(特征工程)和预估器(机器学习)    2.KNN算法(根据邻居确定类别 + 欧氏距离 + k的确定),时间复杂度高,适合小数据    ...

  4. CVE-2012-0158 分析

    目录 CVE-2012-0158 分析&利用 1.实验环境 2.下载poc样本 3.调试并找到漏洞触发点 4.分析漏洞触发模块及流程 5.漏洞利用 6.总结 7.参考资料 CVE-2012-0 ...

  5. DVWA v1.9 新手指南

    DVWA简介 DVWA(Damn Vulnerable Web Application)是一个用来进行安全脆弱性鉴定的PHP/MySQL Web应用,旨在为安全专业人员测试自己的专业技能和工具提供合法 ...

  6. flask的migrate

    https://blog.csdn.net/kevin_qq/article/details/51777190 这个方法可以: https://www.cnblogs.com/caicairui/p/ ...

  7. 安利一个_Java学习笔记总结

    javaIO 字符编码 多线程 线程池 ArrayList遍历方式 LinkedList遍历方式 Vector遍历方式 Vector, ArrayList, LinkedList 的区别是什么? Ha ...

  8. [JXOI2018]排序问题

    嘟嘟嘟 这是今天做的第二道九条可怜的题,现在对他的题的印象是:表面清真可做,实则毒瘤坑人. 首先要感谢吉司机,我期望学的特烂,好在样例直接告诉我们期望怎么求了. 令\(b_i\)表示第\(i\)个不同 ...

  9. 微信硬件平台(八) 3 ESP8266向微信服务器请求设备绑定的用户

    https://api.weixin.qq.com/device/get_openid?access_token=自己申请微信token&device_type=gh_e93c1b3098b9 ...

  10. 为什么我的mac插入耳机耳机没有声音呢?

    macOS 系统莫名其妙就遇到声音和音频播放问题的情况相当普遍,在新添音频设备.应用程序之间进行切换或更新操作系统后,都可能会遇到音频错误.好加在,解决大多数 macOS 声音无法正常工作的方法都非常 ...