上一篇说了如何查看MySQL的执行计划,今天就来看一下数据库的事务相关的知识点。程序员
面试官在数据库这方面最常问的除了sql优化,还有数据库事务、存储引擎等相关知识。上期有人说没有自动门,因此这一期我特意造了自动门,这门没有四五块造不下来。面试
注意:只是CRUD的搬砖工就不须要看了,看了也忘了,只须要拉到最后,点赞、在看、分享,一键三连而后收藏起来就好了。sql
事务是指是程序中一系列严密的逻辑操做,并且全部操做必须所有成功完成,不然在每一个操做中所做的全部更改都会被撤消。数据库
通俗点说就是要么一块儿活,要么一块儿死。并发
事务特性就是普通都知道的ACID,那么什么是ACID,估计有些货跟我以前同样,只知道这个词,不知道每一个字母表明的是什么,此次就给翻译翻译什么叫TMD惊喜(不,说错了,是字母),我还特意下了一个有道词典,浪费了几十M的流量。高并发
A:Atomicity原子性优化
所谓原子性就是说事务是一个最小的单元,跟原子同样不可再分割。一个事务中的全部操做要么所有成功,要么所有失败,经过WAL(Write Ahead Log)实现。(HBASE也应用了这个技术)翻译
I:Isolation隔离性3d
一个事务在操做还未结束以前,对其余事务是不可见的,即一个事务内部的操做及使用的数据对其余的并发事务是隔离的。锁和多版本控制就符合隔离性。版本控制
相似与如今的共享文档:我在编辑文档未保存以前其余人是不可见的。
D:Durability持久性
一旦事务提交,其所作的修改就会永久保存到数据库中。
人也要学会持久,老子没开车。好比健身,深蹲蹲一半怎么行。
C:Consistency一致性
数据库老是从一个一致性的状态转换到另一个一致性的状态,也就是说在某个时间是A,另外一个时间是B。
全部事务对一个数据的读取结果都是相同的,这是由原子性、隔离性、持久性共同保证的结果。
数据的完整性是经过其余三个特性来保证的,包括原子性、隔离性、持久性,而这三个特性,又是经过 Redo/Undo 来保证的,为了保证数据的完整性,提出来三个特性,这三个特性又是由同一个技术来实现的,因此理解 Redo/Undo 才能理解数据库的本质。
READ UNCOMMITTED 未提交读
事务所作的修改,即便未提交,对其余事务也是可见的。事务能够读取未提交的数据,也称为脏读。
也就是说能看见另外一我的正在编辑的内容是什么,毫无隐私可言。
READ COMMITTED 提交读,也称不可重复读
一个事务从开始直到提交以前,所做的修改对其余事务是不可见的。也称为不可重复读,由于执行屡次同样的查询,可能获得不同的结果。
跟未提交读正好相反,我只有保存了文档,你才能看得见。
REPEATABLE READ 可重复读
同一个事务中屡次读取一样的记录的结果是同样的。可能致使幻读,在屡次读取间隙中,可能有其它事务插入新的记录,就会出现幻读。
SERIALIZABLE 可串行化
最高隔离级别,强制事务串行执行,避免了幻读的问题。
也就是事务必须一个一个排队执行,没有插队的状况。
脏读:
一个事务正在对一条记录作修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;这时,另外一个事务也来读取同一条记录,若是不加控制,第二个事务读取了这些“脏”数据,并据此作进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象的叫做"脏读"(Dirty Reads)。
所谓脏读,就是说我没提交别人都能看获得事务,那么后面我删除掉编辑的内容的话他没看,别人仍是觉得我编辑了内容。
不可重复读
一个事务在读取某些数据后的某个时间,再次读取之前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫做“ 不可重复读”(Non-Repeatable Reads)。
幻读
一个事务按相同的查询条件从新读取之前检索过的数据,却发现其余事务插入了知足其查询条件的新数据,这种现象就称为“幻读”(Phantom Reads)。
「注意」
不可重复读和幻读看起来很像,实际上是有差异的。
不可重复读重点在于 UPDATA 和 DELETE,而幻读的重点在于 INSERT
MVCC(Multi-Version Concurrency Control),行级锁的一个变种,在不少状况下避免了加锁操做,开销更低。
经过保存数据在某个时间点的快照来实现。便是无论执行多长时间,每一个事务看到的数据都是一致的。
根据事务开始时间不一样,每一个事务对同一张表,同一时刻看到的数据多是不同的。
其实就是在高并发的访问状态下,对数据进行多版本控制,并经过事务的可见性来保证事务能看到本身应该看到的数据版本。
「那个多版本是如何生成的呢?」
每一次对数据库的修改,都会在 Undo 日志中记录当前修改记录的事务号及修改前数据状态的存储地址(即 ROLL_PTR),以便在必要的时候能够回滚到老的数据版本。
InnoDB的MVCC,是经过在每行记录后面保存两个隐藏的列来实现的。两列,一个保存了行的建立时间,一个保存了行的过时时间(或删除时间),存储的并非实际的时间值,而是系统版本号。每开始一个事务,系统版本号都会自动递增。事务开始时刻的系统版本号会做为事务的版本号,用来和查询到的每行记录的版本号进行比较。
MySQL 的 InnoDB 存储引擎实现隔离级别的一种具体方式,用于实现「提交读」和「可重复读」这两种隔离级别。而未提交读隔离级别老是读取最新的数据行,无需使用 MVCC。可串行化隔离级别须要对全部读取的行都加锁,单纯使用 MVCC 没法实现。
在 MVCC 并发控制中,读操做能够分为两类: 快照读(Snapshot Read)与当前读 (Current Read)。
「快照读」:读取的是记录的可见版本(有多是历史版本),不用加锁。
「当前读」:读取的是记录的最新版本,而且当前读返回的记录,都会加锁,保证其余事务不会再并发修改这条记录。
注意:MVCC 只在 Read Commited 和 Repeatable Read 两种隔离级别下工做。
「如何区分快照读和当前读呢?」
快照读:简单的 select 操做,属于快照读,不须要加锁。
当前读:特殊的读操做,插入/更新/删除操做,属于当前读,须要加锁。
===============================
我是Liusy,一个喜欢健身的程序员。
获取更多干货以及最新消息,请关注公众号:上古伪神
若是对您有帮助,点个关注就是对我最大的支持!!!