mysql的ACID的理解
这是在网上copy下来的ACID的概念,可以直接跳过看后面:
1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。
2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。
3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。
其中,原子性和持久性的概念比较好理解。但是最近发现老是把一致性和隔离性混淆。
个人理解,隔离性主要是针对读操作的。在不同事务之间,读操作隔离。比如另一个事务对数据修改后,会不会影响当前事务的读操作,要不要读到更新后的数据。
一致性,主要强调的是数据的更新是不是“正确”,即,是不是符合我们的预期,这个和读操作应该是要分开看待的,这里应该只强调写操作。
造成我对这俩个概念的混淆的原因是,在java的并发编程中,我们关注的似乎只有一致性,没听说过java并发编程中有什么隔离性。造成这个的原因是,我们使用锁,或者volition来保证数据的读取是“正确”的,这种“正确”性的保证是通过“排他锁“(这里加引号是因为严格来说,和排它锁可能会有轻微的区别,比如cpu的缓存锁,缓存失效机制,但是效果上还是有排他的效果)来保证的。这种锁机制,是比mysql的MVCC,或者读锁更加严格的,也就是说在java并发编程中本质上是没有读锁(或者乐观锁)这种概念的,就算是ReentrantReadWriteLock ,也是一种对mysql的读写锁的仿制,在java的底层是不存在这种东西的。
而mysql中所强调的一致性,就和java并发编程中的一致性基本是一致的了,都是通过排他锁来保证的,所以在对俩者进行编程时,他们俩者的思路是互通的,是可以相互借鉴的。
mysql为了增加并发量,引入了乐观锁,MVCC这种概念,但是也带来了隔离的问题,即因为没有排它的强制性保证,就会出现读和写并发的场景,那么就需要考虑,在俩者并发的场景下,读操作到底该做什么样约束的问题。相反,在java并发编程中,可以理解为,在排它的保证下,是不会出现读和写并发的存在的场景的,也就不会有隔离性的问题。(大家可以想一个java中的lock,还有无锁算法中依赖的CAS底层也会有lock前缀的指令)。
最后,当认识到这些问题的时候,我们在写sql的时候有什么借鉴的意义呢?
个人意见:
1.把不必要引入的隔离性问题,也就是读操作,可以省掉的就省掉。比如 我们要并发的对数据库中一条记录的值进行加一操作。也许可以先select出它的值,然后在java程序中+1,然后再update回去,为了防止并发带来的一致性问题,可以在update的where条件中带上变量的原值。 但是,如果直接update ... set variable= variable +1 这样呢,这样的话,就把读操作,也就是隔离性的问题消除了,全部都转化成了写操作,也就是一致性的问题了,而mysql使用排他策略来进行写,在这种场景下是可以保证一致性的。
2.我们在考虑要不要加事务,要什么样的隔离级别的时候,思路就会更加的清晰。在考虑隔离性的时候,我们首先就知道它强调的是读的操作,那首先就专心考虑我们对读的要求,而不会被其他操作所干扰。
其次,我们需要考虑我们对读回的值做了什么计算,然后是怎样把计算的结果又更新到数据库中的。那么,由于读得到的数据不一定是”正确的“,我们的写操作是否需要加一致性的校验(比如在where条件中加上预期的原值)。
举个例子:还是刚刚的对一个记录并发的加一,假设我们使用先select,然后update的方法,而且我们一个操作单元是多条记录。
首先,由于我们的操作单元是多条记录,所以我们需要原子性,即这批数据要么全部成功,要么全部失败,所以我们对这多次的select,update操作加上了事务。
然后,我们的select应该使用什么样的隔离级别呢?
首先考虑下可重复读,在这种隔离级别下,很有可能读到”不正确“的数据,即别的事务提交了对这个值的修改,但是我们在当前事务中读到的仍然是老的数据,那么导致计算出来的结果肯定是”不正确“的。
然后我们考虑下提交读,那么在这种隔离级别下,不会出现刚刚说的问题了,但是,由于并发的问题,在我们读完后,可能另一个事务提交了对这条记录的修改。这又造成了当前事务中计算结果的错误。
最后,是读未提交,在这种级别下,面临的就是另外一个事务在更新后,然后又回滚所造成的问题了。
那么可以发现,这三种隔离级别都没法满足我们的要求,所以,就会发现,原来我们对隔离性其实没什么必须的要求,我们这里需要的,只是数据一致性的要求。为什么我没有说串行化的隔离级别呢,因为这种隔离级别下,所有的操作都是排他的,是不存在隔离性的问题的。
上面举的这俩个例子都很简单,我们实际的场景也许会比这复杂的多,但是,如果理解了上面说的隔离性和一致性到底指的是什么,我觉得在面对复杂场景时,是可以缕出一条很好的解决思路的。
mysql的ACID的理解的更多相关文章
- 对事务的特性ACID的理解
		对事务的特性ACID的理解 数据库的事务必须具备ACID特性,ACID是指 Atomicity(原子性).Consistensy(一致性).Isolation(隔离型)和Durability(持久性) ... 
- MySQL的COUNT()函数理解
		MySQL的COUNT()函数理解 标签(空格分隔): MySQL5.7 COUNT()函数 探讨 写在前面的话 细心的朋友会在平时工作和学习中,可以看到MySQL的COUNT()函数有多种不同的参数 ... 
- java面试一日一题:讲对mysql的MVCC的理解
		问题:请讲下对mysql中MVCC的理解 分析:这个问题要回答的是对MVCC的理解,以及MVCC解决了什么问题这几个方面入手. 回答要点: 主要从以下几点去考虑, 1.什么是MVCC? 2.MVCC用 ... 
- mysql 执行计划的理解
		1.执行计划就是在sql语句之前加上explain,使用desc 也可以.2.desc有两个选项extended和partitions,desc extended 将原sql语句进行优化,通过show ... 
- SQL Server Mysql 对null值理解的不同
		在说到对null值的理解主要是用unique来体现的.也是说null在unique约束看来是一个值还是多个值的问题. 还是开始实验吧. MYSQL create table t(x int ,cons ... 
- ★ MYSQL隔离级别 通俗理解 + mysql、oracle默认事务隔离级别
		★ 脏读 : 读取了前一事务 未提交 的数据 ; 不可重复读 : 读取了前一事务 提交 的数据: ★ 幻读 与 不可重复读 common :都是读取了另一条已经提交的事务(这点与脏读不 ... 
- mysql 事物ACID和隔离级别
		⑴ 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则 ... 
- 对于事务ACID的理解
		ACID,即以下四点: 原子性(Atomicity) 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生. 一致性(Consistency) 事务前后数据的完整性必须保持一致 ... 
- MySql优化相关概念的理解笔记
		MySQL架构 查询执行流程 查询执行的流程是怎样的: 连接1.1客户端发起一条Query请求,监听客户端的‘连接管理模块’接收请求1.2将请求转发到‘连接进/线程模块’1.3调用‘用户模块’来进行授 ... 
随机推荐
- Windows内核开发之串口过滤
			学习了几个月的内核编程,现在对Windows驱动开发又了更加深入的认识,特别是对IRP的分层处理逻辑有了深入认识. 总结起来就几句话: 当irp下来的时候,你要根据实际情况,进行处理 1> 无处 ... 
- LR实现问答系统查询功能
			脚本中未对问题进行参数化处理,关键点在于关联取值和web_add_header()函数的使用 Action() { web_url("首页", "URL=http://q ... 
- 安装好visual studio后,如何添加新的工作负载和组件
			重新运行visual studio安装程序,出现添加删除组件的界面,勾选即可. 
- SQL数据库索引理解与应用【转贴--收藏】
			SQL数据库中索引分为聚集索引(CLUSTERED)和非聚集索引(NONCLUSTERED)两种. 聚集索引确定表中数据的物理顺序,它就类似与电话簿,按照姓氏排列数据.由于聚集索引规定数据表中的物理顺 ... 
- usb设备驱动的分析
			怎样来分析驱动程序呢? 1.将一个usb设备插入到电脑上,在串口软件上能够显示一些打印信息,用source insight软件打开linux内核2.6.22版本,然后从第一行查找通用的关键字,找到这一 ... 
- 理解javascript中的立即执行函数(function(){})()
			之前看了好多代码,都有用到这种函数的写法,但是都没认真的去想为什么会这样写,今天开始想学习下jquery的源码,发现jquery也是使用这种方式,用(function(window, undefine ... 
- Servlet+JSP例子
			前面两节已经学习了什么是Servlet,Servlet接口函数是哪些.怎么运行.Servlet生命周期是什么? 以及Servlet中的模式匹配URL,web.xml配置和HttpServlet.怎么 ... 
- C运算符
			运算符是一种告诉编译器执行特定的数学或逻辑操作的符号. C 语言内置了丰富的运算符,并提供了以下类型的运算符: 算术运算符.关系运算符.逻辑运算符.位运算符.赋值运算符.杂项运算符 C 中的运算符优先 ... 
- SQL CTE递归
			WITH cte_name AS ( --Anchor member is defined ' UNION ALL --Recursive member is defined referencing ... 
- ASP.NET Core使用NLog记录日志到Microsoft Sql Server
			在之前的文章中介绍了如何在ASP.NET Core使用NLog,本文为您介绍在ASP.NET Core使用NLog记录到Microsoft Sql Server 1.我们需要添加依赖: NLog.We ... 
