MySQL事务处理与并发控制( 四 )

mysql看到START TRANSACTION , 将会禁用自动提交 , 直到用COMMIT或者ROLLBACK结束事务 , 结束之后 , 自动提交模式将恢复到之前的状态 。
为了要显式禁用自动提交模式 , 请使用以下语句:
SET autocommit=0;通过将autocommit变量设置为零禁用自动提交模式后  , 对事务安全型表(例如InnoDB或NDB表)的更改不会立即生效 。你必须使用COMMIT将更改存储到磁盘或ROLLBACK忽略更改 。autocommit是一个会话变量 , 必须为每个会话设置 。要为每个新连接禁用自动提交模式 , 需要修改系统变量 。
一些语句不能回滚 。通常包括数据定义语言(DDL)语句 。
MySQL事务有三种提交模式:

  • 1 自动提交;
  • 2 显示执行commit;
  • 3 因执行DDL , 触发之前的SQL语句自动提交 。
MySQL事务有三种回滚模式:
  • 1 显示执行rollback;
  • 2 因参数 innodb_lock_wait_timeout (表示锁等待发生多久)事务中的语句进行语句级回滚;
  • 3 因参数innodb_rollback_on_timeout 超时导致整个事务回滚(默认情况下 , InnoDB仅回滚事务超时的最后一个语句 。如果指定了--innodb-rollback-on-timeout为ON , 则事务超时会导致InnoDB回滚整个事务 。)
3.2 InnoDB日志技术日志技术是实现数据库原子性和持久性的核心技术 , InnoDB通过UNDO LOG、REDO LOG、doublewrite buffer实现事务的原子性和持久性 。
3.2.1 REDO LOG重做日志是在崩溃恢复期间使用的基于磁盘的数据结构 , 用于纠正由于写入不完整导致数据错误 , 从而保证已提交事务的原子性和持久性 。
为什么需要redo log?
为了提高数据库的性能 , MySQL 中使用了大量的内存 Cache(Innodb 的buffer poll)  , 对数据的修改操作会先修改内存中的 Page , 但这些页不会立刻同步磁盘 , 这时内存中的数据已经和磁盘上的不一致了 , 我们称这种 Page 为脏页 。试想一下这时候如果数据库宕机了 , 内存中这部分被修改的数据记录就丢失了 , 重启后也没办法恢复 。因此需要redo log , 即使数据库不用缓存 , 也需要使redo log , 比如:一个事务写磁盘写了一半 , 数据库重启了 , 重启之后数据库根本无法知道事务进行到何种程度了 。
因此为了保证数据的安全性 , 在修改内存中的 Page 之后 InnoDB 会写 redo log , 因为 redo log 是顺序写入的 , 而众所周知磁盘的顺序读写的速度远大于随机读写 , 因此这部分日志写操作对性能影响较小 。然后 , InnoDB 会在事务提交前将 redo log 保存到磁盘中(可以通过innodb_flush_log_at_trx_commit来控制重做日志刷新到磁盘的策略 。该参数默认值为1 , 表示事务提交必须进行一次fsync操作 , 还可以设置为0和2 。0表示事务提交时不进行写入重做日志操作 , 该操作只在主线程中完成 , 2表示提交时写入重做日志 , 但是只写入文件系统缓存 , 不进行fsync操作 。由此可见 , 设置为0时 , 性能最高 , 但是丧失了事务的一致性) 。这里所说的 redo log 是物理日志而非逻辑日志 , 记录的是数据页的物理修改(比如:将某个页面的某个偏移量处的值加2) , 而不是某一行或某几行修改成怎样怎样 , 它用来恢复提交后的物理数据页(恢复数据页 , 且只能恢复到最后一次提交的位置) 。
当数据库意外重启时 , 会根据 redo log 进行数据恢复 , 如果 redo log 中有事务提交 , 则进行事务提交修改数据 。
3.2.2 UNDO LOG与 redo log 不同 , undo log 一般是逻辑日志 , 根据每行记录进行记录 。例如当 DELETE 一条记录时 , undo log 中会记录一条对应的 INSERT 记录 , 反之亦然当 UPDTAE 一条记录时 , 它记录一条对应反向 UPDATE 记录 。
当数据被修改时除了会记录 redo log 还会记录 undo log , 通过 undo log 一方面可以实现事务回滚 , 另一方面可以根据 undo log 回溯到某个特定的版本的数据 , InnoDB实现 MVCC 的功能时就会用到undo log 。
3.2.3 双写(doublewrite buffer)有了redo log可以用来恢复数据 , 那么doublewrite buffer是做什么的呢?doublewrite buffer也是用于实现数据的持久性的 。


推荐阅读