这是在网上copy下来的ACID的概念,能够直接跳过看后面:java
一、原子性(Atomicity):事务开始后全部操做,要么所有作完,要么所有不作,不可能停滞在中间环节。事务执行过程当中出错,会回滚到事务开始前的状态,全部的操做就像没有发生同样。也就是说事务是一个不可分割的总体,就像化学中学过的原子,是物质构成的基本单位。mysql
二、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。好比A向B转帐,不可能A扣了钱,B却没收到。
三、隔离性(Isolation):同一时间,只容许一个事务请求同一数据,不一样的事务之间彼此没有任何干扰。好比A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转帐。算法
四、持久性(Durability):事务完成后,事务对数据库的全部更新将被保存到数据库,不能回滚。sql
其中,原子性和持久性的概念比较好理解。可是最近发现总是把一致性和隔离性混淆。数据库
我的理解,隔离性主要是针对读操做的。在不一样事务之间,读操做隔离。好比另外一个事务对数据修改后,会不会影响当前事务的读操做,要不要读到更新后的数据。编程
一致性,主要强调的是数据的更新是否是“正确”,即,是否是符合咱们的预期,这个和读操做应该是要分开看待的,这里应该只强调写操做。缓存
形成我对这俩个概念的混淆的缘由是,在java的并发编程中,咱们关注的彷佛只有一致性,没据说过java并发编程中有什么隔离性。形成这个的缘由是,咱们使用锁,或者volition来保证数据的读取是“正确”的,这种“正确”性的保证是经过“排他锁“(这里加引号是由于严格来讲,和排它锁可能会有轻微的区别,好比cpu的缓存锁,缓存失效机制,可是效果上仍是有排他的效果)来保证的。这种锁机制,是比mysql的MVCC,或者读锁更加严格的,也就是说在java并发编程中本质上是没有读锁(或者乐观锁)这种概念的,就算是ReentrantReadWriteLock ,也是一种对mysql的读写锁的仿制,在java的底层是不存在这种东西的。并发
而mysql中所强调的一致性,就和java并发编程中的一致性基本是一致的了,都是经过排他锁来保证的,因此在对俩者进行编程时,他们俩者的思路是互通的,是能够相互借鉴的。事务
mysql为了增长并发量,引入了乐观锁,MVCC这种概念,可是也带来了隔离的问题,即由于没有排它的强制性保证,就会出现读和写并发的场景,那么就须要考虑,在俩者并发的场景下,读操做到底该作什么样约束的问题。相反,在java并发编程中,能够理解为,在排它的保证下,是不会出现读和写并发的存在的场景的,也就不会有隔离性的问题。(你们能够想一个java中的lock,还有无锁算法中依赖的CAS底层也会有lock前缀的指令)。ci
最后,当认识到这些问题的时候,咱们在写sql的时候有什么借鉴的意义呢?
我的意见:
1.把没必要要引入的隔离性问题,也就是读操做,能够省掉的就省掉。好比 咱们要并发的对数据库中一条记录的值进行加一操做。也许能够先select出它的值,而后在java程序中+1,而后再update回去,为了防止并发带来的一致性问题,能够在update的where条件中带上变量的原值。 可是,若是直接update ... set variable= variable +1 这样呢,这样的话,就把读操做,也就是隔离性的问题消除了,所有都转化成了写操做,也就是一致性的问题了,而mysql使用排他策略来进行写,在这种场景下是能够保证一致性的。
2.咱们在考虑要不要加事务,要什么样的隔离级别的时候,思路就会更加的清晰。在考虑隔离性的时候,咱们首先就知道它强调的是读的操做,那首先就专心考虑咱们对读的要求,而不会被其余操做所干扰。
其次,咱们须要考虑咱们对读回的值作了什么计算,而后是怎样把计算的结果又更新到数据库中的。那么,因为读获得的数据不必定是”正确的“,咱们的写操做是否须要加一致性的校验(好比在where条件中加上预期的原值)。
举个例子:仍是刚刚的对一个记录并发的加一,假设咱们使用先select,而后update的方法,并且咱们一个操做单元是多条记录。
首先,因为咱们的操做单元是多条记录,因此咱们须要原子性,即这批数据要么所有成功,要么所有失败,因此咱们对这屡次的select,update操做加上了事务。
而后,咱们的select应该使用什么样的隔离级别呢?
首先考虑下可重复读,在这种隔离级别下,颇有可能读到”不正确“的数据,即别的事务提交了对这个值的修改,可是咱们在当前事务中读到的仍然是老的数据,那么致使计算出来的结果确定是”不正确“的。
而后咱们考虑下提交读,那么在这种隔离级别下,不会出现刚刚说的问题了,可是,因为并发的问题,在咱们读完后,可能另外一个事务提交了对这条记录的修改。这又形成了当前事务中计算结果的错误。
最后,是读未提交,在这种级别下,面临的就是另一个事务在更新后,而后又回滚所形成的问题了。
那么能够发现,这三种隔离级别都无法知足咱们的要求,因此,就会发现,原来咱们对隔离性其实没什么必须的要求,咱们这里须要的,只是数据一致性的要求。为何我没有说串行化的隔离级别呢,由于这种隔离级别下,全部的操做都是排他的,是不存在隔离性的问题的。
上面举的这俩个例子都很简单,咱们实际的场景也许会比这复杂的多,可是,若是理解了上面说的隔离性和一致性到底指的是什么,我以为在面对复杂场景时,是能够缕出一条很好的解决思路的。