你可能知道事务的四大特性,但不一定知道事务的实现原理。:《交易的四大特点是什么?》我:“ACID,即原子性、隔离性、持久性和一致性!”面试官:“MySQL数据库中的InnoDB引擎是如何实现这四个特性的?”我:“这……这……,我还真没看懂。”面试官:“那我们就先这样吧,我们先回去,我们会通知你的~”这可能是一个比较常见的面试场景。你可能已经回答了交易的四大特点,但你不一定知道它的实现原理。今天我们就来谈谈签到交易的四大特点和实现原则。对于原理的实现,本文只是粗略的介绍一下。更多详情可以关注我的后续文章。数据库事务具有四个特性:原子性、隔离性、持久性和一致性。下面将介绍这四个特性的定义以及它们在InnoDB引擎中是如何实现的。原子性定义了一个操作是不可分割的,要么全部成功,要么全部失败。比如我们的转账操作,是不允许发送方成功,收款方失败的。要么全部成功,要么更多失败,中间状态不会出现。InnoDB引擎使用undolog(回滚日志)来保证原子操作。你对数据库所做的每一次数据更改(INSERT、DELETE、UPDATE)都会记录在undolog中,比如下面的操作:你插入一条记录,至少记下这条记录的主键值,然后直接删除回滚时主键值对应的记录。如果删除一条记录,至少要记下这条记录的内容,以便后面回滚时,可以在表中插入一条由这些内容组成的记录。如果你修改一条记录,你至少要记录修改这条记录之前的旧值,这样以后回滚的时候可以把这条记录更新为旧值。当事务执行失败或调用rollback方法时,会触发rollback事件,利用undolog中的数据将数据回滚到修改前的状态。关于undolog的更多信息,我会在后面单独开一篇文章登陆。隔离性是指多个事务并发执行时,事务内的操作与其他事务隔离,并发执行的事务之间不能相互干扰。实现隔离可能会引入脏读、不可重复读、幻读等问题。为了解决这些问题,引入了“隔离级别”的概念。SQL标准事务隔离级别包括:读未提交(readuncommitted)、读已提交(readcommitted)、可重复读(repeatableread)和可序列化(serializable):读未提交:当一个事务还没有提交时,它所做的改变可以被被其他交易看到。Readcommit:一个事务提交后,它所做的修改会被其他事务看到。可重复读:事务执行过程中看到的数据和事务开始时看到的数据总是一致的。当然,在可重复读隔离级别下,未提交的修改对于其他事务也是不可见的。序列化:顾名思义,对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当发生读写锁冲突时,后面访问的事务必须等待前面的事务完成后才能继续执行。根据SQL标准,对于不同的隔离级别,并发事务可能会出现不同严重程度的问题。会更低。InnoDB引擎是如何保证隔离的?使用锁和MVCC机制。这里简单介绍一下MVCC机制,也就是所谓的多版本并发控制。在使用READCOMMITTD和REPEATABLEREAD两种隔离级别的事务下,每条记录在更新时会同时记录一次回滚操作,形成一个Version链,执行普通SELECT操作时访问记录的版本链的过程,所以不同事务的读写和读写操作可以并发执行,从而提高系统性能。持久性定义一旦事务被提交,它对数据库的更改应该是永久的。随后的其他操作或故障不应对其产生任何影响。持久化的实现很简单,就是每次提交事务,就把数据刷到磁盘上,必须保证安全,但是要知道,如果每次事务提交时,都把数据写入磁盘committed,频繁的IO操作,成本太高,数据库的性能极低,所以这种方式不可取。InnoDB引擎是如何解决的呢?InnoDB引擎引入了一个中间层来解决这个持久化问题。我们称这个为重做日志(archivelog)。为什么要引入重做日志?重做日志可以保证数据库的持久性和性能。与直接刷盘相比,重做日志有以下两个优点:重做日志体积小。毕竟,它只记录修改了哪个页面。因此,它体积??小,刷牙速度快。redolog总是追加到最后,属于顺序IO。效率明显比随机IO快。InnoDB引擎是如何做到的?当一条记录需要更新时,InnoDB引擎会先将这条记录写入redolog并更新内存。至此,更新完成。当数据库宕机重启时,redolog的内容会恢复到数据库中,然后根据undolog和binlog的内容回滚或提交数据。redolog比较多,以后打算单独写一篇。ConsistencyDefinitionConsistency简单来说就是数据在执行前后必须处于合法状态。比如身份证号不能重复,性别只能是男或女,高考成绩只能在0到750之间,红绿灯只能3种颜色,房价不能为负等.只有满足这些约束的数据才有效。比如孩子跟你说他高考得了1000分,你就知道他在胡说八道。数据库世界只是现实世界的映射,现实世界中存在的约束当然要在数据库世界中得到体现。如果数据库中的所有数据都符合现实世界中的约束(所有定义的规则),我们说数据是一致的,或者说是一致的。为了保证数据库的数据一致性,应该在以下两个方面下功夫:利用数据库的一些特性来保证部分一致性的要求:比如声明一个列为NOTNULL来拒绝值得插入的NULL等。大多数其中还是需要我们程序员在写业务代码的时候来保证的。
