纯干货,Mysql innodb的ACID特性是怎么实现的?以及高并发情况下会出现的问题
首先说说什么是ACID:
它们分别是Atomicity(原子性),Consistency(一致性),Isolation(隔离性),Transaction(持久性)
原子性:
意为单个事务里的多个操作要么一起成功,要么一起失败.比如现在有三个插入操作,那么前两个成功,第三个失败了,此时,前两个也不再算数,数据库会回滚到事务开始之前的状态.
innodb靠着undo缓冲区实现,也就是当事务开始的时候,首先将会受到影响的行当前的状态保存到undo缓冲区中,一旦失败,则回滚.
一致性:
单个事务对数据库的影响必须要保证是从一个状态到另一个状态的,这个怎么理解呢?将它理解为对原子性的补充就行了,也就是说,你一个事务里三个操作,如果其中一个失败了,其它的也不能对我的数据库造成影响,必须要三个一起成功才行.
这个的实现就是原子性的实现
隔离性:
这个是靠数据库锁实现的,数据库锁实在太繁杂,我这里就说说怎么mysql是怎么保证了在可重复读的情况下就避免了不可重复读和幻读吧.
首先,mysql的读操作在innodb下的读提交和可重复读的情况下都是使用了Mvcc,这个Mvcc将它理解为一个快照就可以了,而读已提交在一个事务里多次读的情况下,每次读都会读最新的已提交的数据.由此也就出现了幻读和不可重复读
比如A线程在一个事务里连续两次select
在第一次select后,B线程插入了一条数据,并且提交了事务.
此时A线程因为每次都是读最新的已提交的数据自然就读到了B线程插入的数据.
而在可重复读的情况下呢?
首先可重复读的情况下读Mvcc每次都是读第一次select的数据,由此就避免了可重复读和幻读的产生,因为B线程插入的数据对线程A的事务没有任何影响,但这样就代表没问题了吗?
假设这样一个场景,线程A要拿到当前最大的ID然后自增之后插入
假设现在数据库最大ID为10
线程A查询后,自增为11,并准备插入
但此时线程B插入一条数据,并且ID为11.
此时线程A插入,然后报错.
由此可见,此时还是会有问题.
那么怎么解决呢?很简单,使用select max(id) from table for update
因为在可重复读的情况下,使用排它锁,会默认升级为间隙排他锁,什么叫间隙排他锁呢?就是会锁离你最近的两个行数据,并且还有他们之间,不让别人进行增删改查操作,如果没有则取无限集.
那么此时,10右区间无限集就被锁起来了,线程B自然没法查询数据(当然也有可能是A,看谁先拿到锁).此时线程A就插入成功,然后B开始查询,之后插入(这里说下为什么是排他锁而不是共享锁呢?因为线程A和线程B在并发的情况下查了max(id)后,他们拿到的都是相同的数据,也就会在插入的时候报错,所以此时直接让他们其中一个堵在select那里,这样另一方拿到数据后,就会更新id,另一方也能拿到最新值了)
持久性:
事务提交后,事务里的数据必须要进行刷盘,也就是强同步
这里要插一句的是,当事务提交后,数据本身不会马上刷盘,而是由一个redo缓冲区保存了插入日志,进行刷盘,为什么要这样做呢?因为redo是日志数据,所以可以顺序写,而数据刷盘则是要找到文件里数据所在的索引,也就是随机写,而随机写比顺序写慢很多,毕竟多了硬盘寻址的操作.
纯干货,Mysql innodb的ACID特性是怎么实现的?以及高并发情况下会出现的问题的更多相关文章
- Mysql高并发情况下的解决方案(转)
查询了下Mysql 关于高并发的处理的资料,在这记录一下. 高并发大多的瓶颈在后台数据逻辑处理,在存储,mysql的正常的优化方案如下: 1.代码中sql语句优化 2.数据库字段优化,索引优化 3.加 ...
- Mysql在高并发情况下,防止库存超卖而小于0的解决方案
背景: 本人上次做申领campaign的PHP后台时,因为项目上线后某些时段同时申领的人过多,导致一些专柜的存货为负数(<0),还好并发量不是特别大,只存在于小部分专柜而且一般都是-1的状况,没 ...
- 深入学习MySQL事务:ACID特性的实现原理
事务是MySQL等关系型数据库区别于NoSQL的重要方面,是保证数据一致性的重要手段.本文将首先介绍MySQL事务相关的基础概念,然后介绍事务的ACID特性,并分析其实现原理. MySQL博大精深,文 ...
- MySQL事务及ACID特性
一.事物 1.定义:事务是访问和更新数据库的程序执行单元,事务中包含一条或者多条SQL语句,这些语句要么全部执行成功,要么都不执行. 在MySQL中,事务支持是在引擎层实现的,MySQL是一个支持多引 ...
- 一文说尽MySQL事务及ACID特性的实现原理
MySQL 事务基础概念 事务(Transaction)是访问和更新数据库的程序执行单元:事务中可能包含一个或多个 sql 语句,这些语句要么都执行,要么都不执行.作为一个关系型数据库,MySQL 支 ...
- MySql计数器,如网站点击数,如何实现高性能高并发的计数器功能
MySql计数器,如网站点击数,如何实现高性能高并发的计数器功能 Clicks: Date: -- :: Power By 李轩Lane TagMysql计数器高性能 现在有很多的项目,对计数器的实现 ...
- 【转】记录PHP、MySQL在高并发场景下产生的一次事故
看了一篇网友日志,感觉工作中值得借鉴,原文如下: 事故描述 在一次项目中,上线了一新功能之后,陆陆续续的有客服向我们反应,有用户的个别道具数量高达42亿,但是当时一直没有到证据表示这是,确实存在,并且 ...
- 搞懂MySQL InnoDB事务ACID实现原理
前言 说到数据库事务,想到的就是要么都做修改,要么都不做.或者是ACID的概念.其实事务的本质就是锁和并发和重做日志的结合体.那么,这一篇主要讲一下InnoDB中的事务到底是如何实现ACID的. 原子 ...
- [纯干货] MySQL索引背后的数据结构及算法原理
摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...
随机推荐
- Kubenetes里pod和service绑定的实现方式
我之前的文章 如何在Kubernetes里创建一个Nginx service介绍了如何创建一个Kubernetes pod和service,使用的方法是命令kubectl run. 本文介绍另一种方式 ...
- 解决Starting to watch source with Jekyll and Compass. Starting Rack on port 4000
问题 Starting to watch source with Jekyll and Compass. Starting Rack on port 4000 rake aborted! Errno: ...
- 单调栈2 POJ3250 类似校内选拔I题
这个题再次证明了单调栈的力量 简单 单调栈 类似上次校内选拔消砖块 一堆牛面朝右排 给出从左到右的 问每个牛的能看到前面牛发型的个数之和 //re原因 因为在执行pop的时候没有判断empty 程序崩 ...
- Luogu P4463 [国家集训队] calc
WJMZBMR的题果然放在几年后看来仍然挺神,提出了一种独特的优化DP的方式 首先我们想一个暴力DP,先定下所有数的顺序(比如强制它递增),然后最后乘上\(n!\)种排列方式就是答案了 那么我们容易想 ...
- myeclipse 导入项目时no projects are found to import解决办法
myeclipse 识别一个工程需要.classpath与.project文件,一般无需提交SVN所以项目切下来的时候是没有这两个文件的. 方法1: 1) 在myeclipse中新建一个和你要导入的项 ...
- jsTree展开根节点 设置用户图标
$("#jstree").on("loaded.jstree", function (event, data) { var n = 0; var root = ...
- shell脚本,对MySQL数据库进行分库加分表备份
[root@localhost wyb]# cat table_backup.sh #!/bin/bash flag= user=root pass=test mysql -u$user -p&quo ...
- javascript 写一个随机范围整数的思路
const {random} = Math; //返回 [min,max] 的随机值 //[0,1) * (max - min + 1) => [0,max-min+1) //[0,max-mi ...
- 【数位dp】bzoj1799: [Ahoi2009]self 同类分布
各种奇怪姿势的数位dp Description 给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数. Sample Input 10 19 Sample Output 3 HINT [约束条 ...
- 【Git版本控制】Git使用教程
1.Git的综述 SVN是集中式版本控制系统,版本库集中放在中央服务器上,而干活时用的都是自己的电脑,所以首先要从中央服务器哪里得到最新的版本,然后干活,干完后,需要把自己做完的活推送到中央服务器.集 ...