目录一. 事务的基本概念二. 事务的处理原则三. 事务的ACID特性3.1 原子性(Atomicity)3.2 一致性(Consistency)3.3 隔离性(Isolation)3.4 持久性(Durability)四. 事务的状态五. 隐式事务六. 显式事务七. MySQL的哪些引擎支持事务一. 事务的基本概念事务是一组具有操作逻辑的单元它可以使一组数据由一种状态转变为另一种状态。我来解释一下这句话什么意思。一组具有操作逻辑的单元我们知道关于数据库我们最常做的就是增删改查操作那么一条 增/删/改/查 语句就可以看成是一个操作单元那么我们这里所理解的一组这个数量单位是至少大于等于二。也有很少一些事务是由一个SQL语句形成的很少遇到但各位同学也要知道这一点。一组数据由一种状态转变为另一种状态就以两个银行账户为例A账户给B账户赚钱那么A转了多少A账户就应该扣除多少B账户就应该增加多少不应该说A扣了但B没加上或者A账户未扣钱但B账户却加钱了这种情况不应该存在也不能存在。对于A账户和B账户整体来说我们想要的结果是不管A对B转账还是B对A转账经过转账后两个账户都应该是符合逻辑的一组数据转账后两个账户的余额总和应该与转账前相同我们不关心中间发生了什么。将上面两段话总结概括我们就会对事务有一个简单的了解了。事务就是至少两条 SQL 语句构成的一组执行单元在执行完这一组语句之后得到的最终结果其状态应该是符合逻辑的并且是合法的只不过是从原来的一种状态变成了另一种状态。二. 事务的处理原则我们再提到上面转账的那个例子A账户给B账户赚钱不能存在A账户扣钱了B账户没加钱或A账户未扣钱但B账户加钱这种状态。为了避免这种情况的发生事务就有一个处理原则即使出现了故障也不会改变这种原则。当一个事务执行多个操作时要么将所有的操作全部提交(commit)将数据全部永久保存下来要么数据库就放弃做的所有修改就算有些操作已经完成了也必须将整个事务回滚(rollback)到最初的状态。三. 事务的ACID特性3.1 原子性(Atomicity)我们通常说原子是宇宙最小的单位这句话也正是想体现出这一点。也就是说我们的事务虽然是由一组SQL语句构成的但在我们看来它就是一个最小的执行单元不能将它们分割。这一组事务执行完成之后要么全部成功提交要么全部回滚到最初状态不能说我这个事务有几十条SQL语句执行到最后一步有失败发生然后将前面做的全部提交失败的回滚这样绝对不行。只要这个事务中的所有语句没有全部执行成功并且提交即使前面的SQL语句已经完成也必须回滚不能将这些语句分割这就是原子性。3.2 一致性(Consistency)一致性主要是说我们事务中的SQL语句再执行完毕后其得到的结果应该是从一个合法状态转变成了另一种合法状态这里说的合法是我们生活层面上理解的是否合法而不是说我们的SQL语句是否合法。举个栗子A账户对B账户转账A扣100首先要判断A是否足够100如果不够扣那么这条语句执行后就是不合法的再者如果A成功扣除100但是B未加上100这也是不合法的因为前后一致性不一致我们希望得到的逻辑结果是B加上100A和B两账户总金额之和不变这就是一致性。3.3 隔离性(Isolation)隔离性是指一个事务在执行时不能被其他事务影响我们可以从多线程的角度来来理解。如上图是A账户对B账户转两次账两次都是转50我们把这两次操作可以分为两个线程去执行。理想情况下我们希望是事务1与事务2都按照下方的顺序挨个去执行第一步把A账户的余额读到磁盘去第二步执行A账户扣钱操作第三步将A的150写入磁盘第五步将B的余额读到磁盘第六步执行B账户加钱操作第七步将B的50写入磁盘但实际上如果我们没有给事务添加隔离性就等于是上述这七步操作每一步都有可能有别人中途打断就像上面图中的情况最后一步B要写入磁盘了还没来得及写呢事务2进入先执行完了执行完成之后恰好值为50然后又执行事务1中的写入50操作这样执行下来A账户剩余100但B账户只有五十它们虽然都成功完成了满足原子性但是不满足我们刚才说的一致性A与B之后由之前的200变成了150。3.4 持久性(Durability)持久性在事务上的意思就是我们执行的操作一旦完成就会持久性地保存在数据库中对数据库中数据发生的变化是永久性保存的。举个例子张三向李四转了100块转账完成之后后悔了但现在事务已经完成了所以张三不可能从事务的层面上让刚才发生的转账回滚因为转账事务已经完成了数据的操作也已经永久化的保存到了数据库中如果张三想把钱要回来不能回滚刚才的事务只能让李四再转回来这个时候注意李四再转回来它就是另外一个事务了和刚才的事务不矛盾不冲突。四. 事务的状态如上图就是一个事务在执行过程中可能发生的状态。活动的(active)表示该事务正在正常进行部分提交的(partially committed)表示事务中部分逻辑语句已经执行完成这里的提交指的是内存层面的提交还没有写到磁盘上去提交的(committed)表示事务顺利完成数据也成功提交写入磁盘失败的(failed)当处于正常活动时如果发生错误(数据库自身错误服务器宕机断电等)或者人为性的手动停止就会进入失败状态部分提交状态也可以进入失败状态因为一部分语句成功完成不代表事务中剩余的语句会顺利完成如果失败数据就要全部进行回滚中止的(aborted)如果事务进入失败状态在回滚之后就会进入到中止状态事务将不再继续进行。五. 隐式事务在我们常用的 MySQL 数据库中隐式事务是默认开启的而且每条单独的 SQL 语句都是一个单独的事务。如下图 student 学生表我简单添加了几个数据然后我对该表 studentno 2 的学生姓名做修改这条修改语句就是一个隐式事务执行完毕后会自动将结果提交。如下所示语句执行成功我们回到学生表刷新查看修改成功我们也可以看到在 update 语句中我们没有任何关于事务的关键字它只要执行就会直接将结果进行自动提交将受影响后的结果呈现出来。在实际业务开发的过程中我们的一个业务需求通常会执行多条 SQL 语句一旦程序出现错误就需要全部回滚。如果我们使用隐式事务根本达不到这样的效果因为隐式事务默认开启并且每条语句都是一个事务这样我们即使执行事务中得一条SQL语句也会马上提交而事务具有持久性一旦提交就无法回滚了因此在实际业务开发时我们通常会使用显式事务。六. 显式事务刚才简单说了一下隐式事务下面我们说一下显式事务。在 MySQL 数据库中显式事务可以使用关键字 START TRANSACTION 或 BEGIN 开启后面还可以跟 read only只读read write读写with consistent anapshot一致性读。read only 表示事务只能进行查询操作不能进行增删改操作read write 表示事务既能进行查询操作也能进行增删改操作with consistent anapshot 可以和 只读与读写 两种操作搭配使用还有一些情况下可能我们的事务需要进行很多操作但有一步操作做错了我们就需要回滚到最初状态但我们觉得回滚到最初状态太麻烦就可以在中间某个地方设置一个保存点 savepoint我们回滚就会回滚到保存点然后我们可以考虑继续回滚到最初状态或者是重新执行业务。如下代码所示START TRANSACTION READ_WRITE # READ_WRITE 即可读又可写 UPDATE student SET student.name 张女士 WHERE student.studentno 2 SAVEPOINT #定义一个回滚点当我们想回滚时就可以回滚至此处 UPDATE student SET student.name 张先生 WHERE student.studentno 2 COMMIT; # COMMIT 手动提交事务七. MySQL的哪些引擎支持事务想要查询 MySQL 的那些引擎支持事务我们只需要在 MySQL 执行SHOW ENGINES命令如下图所示从上图我们可以看到只有 MySQL 默认的 InnoDB 存储引擎是支持事务的Transactions 即事务XA 指分布式事务如果一个引擎支持分布式事务那么它也一定支持事务。