【书 : InnoDB 存储引擎】第 7 章 事务

7.1  认识事务

7.1.1 概述

在事务中的操作, 要么都做修改, 要么都不做, 这就是事务的目的,也是事务模型区别与文件系统的重要特征之一。

A 原子性,

C 一致性,

I 隔离性,也可称为并发控制, 可串行化, 锁

每个读写事务的对象对其他事务的操作对象能相互分离

D 持久性


7.1.2 分类

扁平事务

带有保存点的扁平事务

链事务,  可视为保存点模式的一种变种。

嵌套事务, 是一个层次结构框架

分布式事务


7.2 事务的实现

原子性,一致性,持久性通过数据库的 redo log 和 undo Log 来完成。 redo log 称为重做日志, 用来保证事务的原子性和持久性。 undo log 用来保证事务的一致性。

redo 和 undo 不是 逆过程。redo 恢复提交事务修改的页操作, 而 undo 回滚行记录到某个特定版本。两者记录的内容不同, redo 通常是物理日志, 记录的是页的物理修改操作。 undo 是逻辑日志, 根据每行记录进行记录。

7.2.1 redo

1 基本概念

重做日志用来实现事务的持久性, 其由两部分组成: 一是内存中的重做日志缓存(redo log buffer),其是易失的; 二是日志文件(redo log file),其是持久的。

InnoDB 事务引擎,通过 Force Log at Commit 机制实现事务的持久性, 即当事务提交(commit)时, 必须先将该事务的所有日志写入到重做日志文件进行持久化, 待事务的 commit 操作完成才算完成。// 这部分写的有问题, 没分清 重做日志是只有 redo log 还是 redo log 和 undo log 两个。

redo log 基本都是顺序写的, 在数据库运行时不需要对 redo log 的文件进行读取操作, 而 undo log 是需要随机读写的。

为了确保每次日志都写入重做日志文件, 在每次将重做日志缓冲写入重做日志文件后, InnoDB 引擎都需要调用一次 fsync 操作。

由于fsync 的效率取决于磁盘的性能, 因此磁盘的性能决定了事务提交的性能, 也就是数据库的性能. // 待理解,是说数据库的性能取决于事务的性能?

参数 innodb_flush_log_at_trx_commit ,默认为 1 。 用来控制重做日志刷新到磁盘的策略。

0 表示提交时不进行写入重做日志操作,这个操作仅在 master thread 中完成, 而在 master thread 中每一秒会进行一次重做日志的 fsync 操作。//最快  

1 表示会将重做日志缓冲中的日志写入文件, 并调用一次 fsync 操作。 //最慢, 在执行 commit 时将重做日志缓冲同步到磁盘

2 表示事务提交时将重做日志写入重做日志文件, 但仅写入文件系统的缓存中, 不进行 fsync 操作。//中间 将重做日志异步写到磁盘,即写到文件系统的缓冲, 不保存执行 commit 时肯定会写入重做日志文件。

2 log block

在 InnoDB 中,重做日志都是以 512 字节进行存储的。 

日志块由三部分组成, 依次为日志块头(log block header), 日志内容(log body), 日志块尾(log block tailer)。

3 log group

4 重做日志格式


7.2.2 undo

1 基本概念

事务的回滚, 需要 undo

undo 是逻辑日志, 因此只是将数据库逻辑地恢复到原来的样子。 所有修改都被逻辑地取消了, 但是数据结构和页本身在回滚之后可能大不相同。因此不能将一个页回滚到事务开始的样子, 因为这样会影响其他事务正在进行的工作。

除了回滚操作, undo 的另一个作用是 mvcc ,即在 InnoDB 引擎中 MVCC 的实现是通过 undo 来完成。// 待扩充

undo log 会产生 redo log , 也就是 undo log 的产生会伴随着 redo log 的产生, 因为undo log 也需要持久性保护。

2  undo 存储管理

show engine innodb status\G

history list length 代表了 undo log 的数量。

3 undo log 格式

undo log 分为:

insert undo log

update undo log

4 查看 undo 信息

//mysql 5.6 的 information_schema 数据库中,

//找不到表 INNODB_TRX_ROLLBACK_SEGMENT, INNODB_TRX_UNDO


7.2.3 purge

delete 和 update 操作可能并不直接删除原有的数据。

delete from t where a  = 1;

表 t 上 列 a 有聚集索引(主键), 列 b 上有辅助索引。 对于 delete 操作, 仅是将主键列等于 1 的记录 delete flag 设置为 1, 记录并没有被删除, 即 还是存在 B+ 数中。 其次, 对辅助索引上 a 等于 1 , b 等于 1 的记录同样没做任何处理, 针织没有产生 undo log 。 真正的删除这行记录的操作被 “延时”了, 最终在 purge 操作中完成。

purge 用来完成最终的 delete 和 update 的操作。 因为 innoDB 存储引擎支持 MVCC, 所以记录不能在事务提交时立即处理,这时其他事务可能正在引用这行, 故 innoDB 需要保存记录之前的版本。 是否可以删除通过 purge 判断。

为了节省存储空间, 一个页上允许多个事务的 undo log 存在。

全局动态参数 innodb_purge_batch_size 用来设置每次 purge 操作需要清理的 undo  page 数量, 从 1.2 版本开始,默认值为 300. 

全局动态参数 innodb_max_purge_lag 用来控制history list 的长度。默认值为 0

7.2.4 group commit

一次 fsync 可以刷新确保多个事务日志被写入文件, 事务提交时会进行两个阶段的操作:

1) 修改内存中事务对应的信息, 并且将日志写入重做日志缓冲。

2)调用 fsync 将确保日志都从重做日志缓冲写入磁盘。

步骤2)相对 1) 是一个较慢的过程, 因为要与磁盘打交道。

保证 二进制日志的写入顺序和 InnoDB 的事务提交顺序,为了备份和恢复的需要。

7.3 事务控制语句

commit 和commit work 语句基本一致, 都用来提交事务。 不同之处 commit work 用来控制事务结束后的行为是 chain 还是 release。 若果是 chain 方式, 那么事务变成了 链事务。

通过用 completion_type 来控制是否是链事务

默认为 0 , 没有任何操作, commit 和 commit work 等价

设置为 1 , commit work 自动开启一个链事务, 不用显示的 begin 

设置为 2 , commit work 等同与 commit and release。 在事务提交胡会自动断开与服务器的连接


7.4 隐式提交的 SQL 语句

执行完相应语句后, 会有一个隐式的 commit 操作。此时 执行 rollback 将不可以回退

7.5 对于事务操作的统计

show global status like 'com_commit'


7.6 事务的隔离级别

READ UNCOMMITTED

READ COMMITTED 除了唯一性的约束检查及外键约束的检查需要 gap lock, InnoDB 引擎不会使用 gap lock 的锁算法。

REPEATABLE READ  使用next-key lock 锁算法, 避免幻读问题产生。

SERIALIZABLE 在此级别, InnoDB 会对每个 select 语句自动加上 lock in share mode 。 且主要用于 InnoDB 存储引擎的分布式事务。


7.7 分布式事务

7.7.1 MySql 数据库分布式事务

例子: 北京的张三转 1000 块钱到 上海的李四账户

在 PHP 中的实现:http://php.net/manual/zh/mysqlnd-ms.quickstart.xa_transactions.php


7.7.2 内部 XA 事务

另一种分布式事务:在存储引擎与插件之间,或在存储引擎与存储引擎之间。

例如:写 innodb redo 日志和 binlog 日志,要保持一致性时用到


7.8 不好的事务习惯

7.8.1 在循环中提交

7.8.2 使用自动提交

使用 start transaction, begin 来显示地开启一个事务。 在显示开启事务后, 在默认设置下(completion_type 等于 0), mysql 会自动执行 set autocommit = 0 的命令, 并在 commit 或 rollback 结束一个事务后执行 set autocommit = 1.

7.8.3 使用自动回滚

7.9 长事务

将长事务分为若干短事务来执行。

例如:在银行系统中, 将一亿用户添加利息的操作,分为没十万个一个事务。来完成。好处是 1 不用完全回滚;2 知道进度。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容