《MySQL技术内幕-InnoDB存储引擎》学习笔记五-数据库事务
2019-07-18 ヾ(◍°∇°◍)ノ゙ 不要拦着我 我还能学一会儿
第7章 事务的东东
简单的说说:就是数据库区别于文件系统的重要特征之一了。就是事务是访问更新数据库数据的一个单元,在这个事务单元中所有的修改,要么都成功,要么都失败。好像就酱紫。
概述与分类
常说的数据库特性
- **原子性(atomicity):**就是事务操作为最小单位,要么都成功,要么都失败。
- **一致性(consistency):**不知道是啥 (ノ`Д)ノ
- **隔离性(isolation):**不同事务之间的数据不会相互影响。
- **持久性(durability):**事务完成后,数据就为永久性的了(数据不可逆并持久化存储于存储系统当中)
就是常说的啥ACID特性。具体干啥用的,不知道。但并不是所有数据库都完全满足这4个特性的。【比如:oracle 数据库,默认事务级别为READ COMMITTED,就不满足隔离性的了。】
事务的分类
- 扁平事务 :就是简单的单个 begin 、commit、rollback这样子。
- 带有保存点的扁平事务:在一个事务中有好几个保存点用于部分回滚的东东。
- 链事务:一个事务结束之后调用另一个事务。(之间有数据结果传递)
- 嵌套事务:一个事务中 调用另外的子事务。(常见存储过程之间调用,好像相互调用会死锁或死循环的样子)
- 分布式事务: 是多个节点间的扁平事务集合。(栗子:招行转账到工行,这个操作了两个节点的数据。需要分布式事务,要么都成功,要么都失败。虽然这个事务常见处理时在业务层面完成的。)
注意:InnoDB是不支持嵌套事务的,ε=(´ο`*)))唉 。。。。。
事务特性的实现
数据库的事务是要满足ACID特性的:
- 隔离性:由 锁 来实现
- 原子性、一致性、持久性:由数据库的redo log 和 undo log 来实现;
redo log为重做日志,用来保证事务的原子性和持久性。(物理页日志)
undo log为回滚日志,用来保证事务的一致性。(逻辑行日志)
关于各种日志
redo 重做日志
是InnoDB开启事务的时候,就一直在记录重做日志,在commit的时候,会把所有日志写到重做日志文件进行持久化保存。【这个动作为同步fsync操作】
默认配置操作为commit的时候同步,但是也可以配置 略
重做日志,分为两个部分:内存中的重做日志缓冲,和 重做日志文件。
然后这里面还有啥log block (重做日志块)、log group(重做日志组)、LSN(日志序列号)等等的东西,都不用管啦,引擎自行处理就好了。
查看重做日志情况:
SHOW ENGINE INNODB STATUS;中的Log sequence ...Log flushed up to ...Last checkpoint at .......
看看就好了。
undo 回滚日志
是一种逻辑日志,用于将数据库逻辑地恢复到原来的样子。
show VARIABLES LIKE 'innodb_undo%'
可以用这个语句来查询一点简单的信息。
而关于这个回滚日志的其他的东东,我也看不懂了(ノ`Д)ノ 反正都是InnoDB自己处理的。
其他操作
purge 清空操作
delete 和update 操作,并不会真正的删除原有的记录,只是标记页记录中的标志位。真正的删除是有purge这里来操作完成的。
是按照一个history list 进行undo log 的查找,并处理清除数据的。对已其他的配置,正常人就不用去调整了。。。
group commit
就是一次同步刷新多个事务日志到文件。略
以上这些乱七八糟的操作,反正都是建议按InnoDB原本的配置就可以了。(:з」∠)
事务控制
默认情况下,MySQL是自动提交的。就是在执行完一个sql之后,自动就会commit。
常用的语句命令
- start transaction | begin :显示开启事务
- commit: 显示事务提交
- rollback:回滚操作,回滚会结束用户事务,并撤销为提交的修改。
- savepoint identifier : 允许始终中添加多个保存点
- release savepoint identifier : 删除事务保存点,如果没有保存点会抛出异常
- rollback to [savepoint] identifier:回滚事务到保存点,但是并没有结束事务
- set transaction:设置事务隔离级别。在前一篇锁的笔记里面有
这些的事务控制的命令,在做存储过程的时候是会用上了,普通代码的CURD是不会用到的
分布式事务
InnoDB存储引擎是支持XA事务的,也就是分布式事务。(XA使用的是两次提交的事务解决方案)
通常来说,分布式事务是使用编程语言来完成操作的。比如:**Java的JTA(Java Transaction API)**可以很好的支持Mysql的分布式事务,具体怎么用。。。。。鬼知道啊。。。(ノ`Д)ノ 用到的时候再说吧,现在接手的业务还没到这个级别。
事务的问题
循环提交
正常在存储过程中循环更新数据的时候,虽然没有显示的提交【commit】,但是数据库默认会自动提交的。也就是说,每一次的更新都会进行一次的日志同步,这个是很会花时间的。【即使是用了BEGIN,并且在循环中没有显示commit】
所以,正确的加快速度的做法是,显示的
START TRANSACION
开始事务,在完成后COMMIT
。这样只会进行一次的重做日志同步。
自动提交
这个就是前边说的情况,默认情况下Mysql是自动提交的,在大数据更新的时候可能会影响速度。
自动回滚
说的是代码(存储过程)中使用异常捕获,然后自动回滚:像这样
CREATE PROCEDURE XXXXXXX() BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK ; -- DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ...插入异常日志... END ; ......... END;
我觉的挺好啊,不过就是会丢失了,数据库异常返回的信息而已 ╮(╯_╰)╭;
觉得这个异常捕获可以做一些日志的插入,还是很好的;
长事务
就是执行时间几个小时的事务,需要进行分解为小的事务来处理。(比如处理n亿级别的数据)
虽然,这个级别的数据量我是遇不到的╮(╯_╰)╭
小结一下
这里由于事务的情况,会建议使用row格式的二进制日志。
然后主要就是最后一些事务上的问题需要开发的时候注意一下,以及事务开启的命令要会用【在存储过程中】。就酱紫即可
2019-07-26 小杭
最近一周一篇的学习进度,好累。。"( ̄(エ) ̄)ゞ