savepoint原理
保存点
在MySQL中, 保存点SAVEPOINT属于事务控制处理部分。利用SAVEPOINT可以回滚指定部分事务,从而使事务处理更加灵活和精细。SAVEPOINT相关的SQL语句如下
SAVEPOINT identifier
设置SAVEPOINT。如果重复设置同名savepoint,新的会覆盖老的.
RELEASE SAVEPOINT identifier
释放SAVEPOINT。
ROLLBACK [WORK] TO [SAVEPOINT] identifier
回滚到指定的SAVEPOINT。
InnoDB内部实现
保存点跟事务有关,因此我们这里只讨论事务引擎InnoDB的savepoint实现。
首先看server层保存点结构:
struct st_savepoint {
struct st_savepoint *prev;
char *name; /* 名字 */
uint length;
Ha_trx_info *ha_list; /* 设置savepoint时已注册的插件 */
/** State of metadata locks before this savepoint was set. */
MDL_savepoint mdl_savepoint;
};
InnoDB层保存点结构:
保存点结构:
struct trx_named_savept_t{
char* name; /*!< savepoint name */
trx_savept_t savept; /*!< the undo number corresponding to
the savepoint */
ib_int64_t mysql_binlog_cache_pos;
/*!< the MySQL binlog cache position
corresponding to this savepoint, not
defined if the MySQL binlogging is not
enabled */
UT_LIST_NODE_T(trx_named_savept_t)
trx_savepoints; /*!< the list of savepoints of a
transaction */
};
链表存储事务上的所有保存点:
trx_t
{
UT_LIST_BASE_NODE_T(trx_named_savept_t)
trx_savepoints;
…….
}
保存点最重要的信息,事务回滚日志的序号:
struct trx_savept_t{
undo_no_t least_undo_no; /*!< least undo number to undo */
};
SAVEPOINT与UNDO日志
事务回滚通过回滚UNDO日志来实现,同样,回滚至保存点也是通过应用UNDO日志来实现。
InnoDB事务在每次修改操作时都会记录UNDO日志,参见函数trx_undo_report_row_operation,每次操作都会记录UNDO日志序号记为undo_no,每次操作undo_no都会递增。回滚只需要反向应用UNDO日志即可。 SAVEPOINT与undo_no是一一对应的。
create table t1(c1 int primary key);
begin;
insert into t1 values(1);
savepoint a;
insert into t1 values(2);
savepoint b;
insert into t1 values(3);
rollback to savepoint a;
commit;

SAVEPOINT与BINLOG
InnoDB开启binlog的情况下,savepoint回滚的那段操作不应记录binlog. 我们知道,事务执行过程中产生的binlog先写入cache中,提交时再将cache中的数据写binlog文件中。 然而,savepoint回滚时,binlog还在cache中,那么被回滚的那段操作的binlog需要从cache中清理掉。
设置savepoint时,记录binlog在cache中起始位置。
trans_savepoint
->ha_savepoint
->binlog_savepoint_set
->binlog_trans_log_savepos
回滚至savepoint时,从保存的起始位置清理cache
trans_rollback_to_savepoint
->ha_rollback_to_savepoint
->binlog_savepoint_rollback
->binlog_trx_cache_data::restore_savepoint
->binlog_cache_data::truncate
->reinit_io_cache
SAVEPOINT与锁
回滚保存点以后,此保存点以后的保存点都会释放,但此保存点以后InnoDB层操作加的锁不会释放。这里不释放锁,是为了不破坏两阶段锁协议,减少死锁的发生。
而对于MDL(metadate lock)锁,在binlog关闭的情况下可以提前释放。 而binlog开启的情况下,需考虑如下情况:
如果操作的仅是InnoDB表且InnoDB层没有加锁,则MDL锁可以释放,否则,不能释放。 InnoDB层持有锁,如果释放MDL可能出现死锁。考虑如下情况: trx 1: rollback to savepoint xxx; InnoDB层持有t1的行锁,释放t1的MDL trx 2: 操作t1; 持有t1的MDL, 等待t1行锁 trx 1: 再次操作t1; 等待t1的MDL锁,从而构成死锁。
如果操作中有非事务引擎,则不能释放MDL锁。 如果是非事务引擎,例如t1为MyiSAM表。 ... begin; insert into t1 values(1); savepoint a; insert into t1 values(2); rollback to savepoint a; commit; ... savepoint和rollback to savepoint之间的sql都会写入binlog. 如果提前释放MDL,其他会话drop table t1可以成功,这样会导致应用binlog时,执行insert into t1 values(2);会找不到表t1。
SAVEPOINT作用域
按官方文档 中,store function和trigger会重新开启新的savepoint作用域, store function和trigger完成后老的savepoint作用域重新可用。
A new savepoint level is created when a stored function is invoked or a trigger is activated. The savepoints on previous levels become unavailable and thus do not conflict with savepoints on the new level. When the function or trigger terminates, any savepoints it created are released and the previous savepoint level is restored.
delimiter //
drop procedure if exists p1//
create procedure p1()
begin
release savepoint a;
end//
delimiter ;
begin;
savepoint a;
call p1();
rollback to savepoint a;
ERROR 1305 (42000): SAVEPOINT a does not exist
从结果来看与官方文档描述并不一致。
实际从代码中上看,stored function和trigger并没有开启独立的事务,而是与调用着共用同一事务。savepoint都在同一事务的链表中,因此store function和trigger中的savepoint作用域和调用者相同。
官方对savepoint的实现并不彻底。
匿名SAVEPOINT
实际上,InnoDB事务中每个语句执行前都会记录一个匿名savepoint;如果当前语句执行失败,不会回滚整个事务,而是利用这个匿名savepoint回滚失败的语句。
struct trx_t{
trx_savept_t last_sql_stat_start; //匿名savepoint
......
savepoint原理的更多相关文章
- [Flink原理介绍第四篇】:Flink的Checkpoint和Savepoint介绍
原文:https://blog.csdn.net/hxcaifly/article/details/84673292 https://blog.csdn.net/zero__007/article/d ...
- mysqldump和xtrabackup备份原理实现说明
背景: MySQL数据库备份分为逻辑备份和物理备份两大类,犹豫到底用那种备份方式的时候先了解下它们的差异: 逻辑备份的特点是:直接生成SQL语句,在恢复的时候执行备份的SQL语句实现数据库数据的重现. ...
- mysqldump的实现原理
对于MySQL的备份,可分为以下两种: 1. 冷备 2. 热备 其中,冷备,顾名思义,就是将数据库关掉,利用操作系统命令拷贝数据库相关文件.而热备指的是在线热备,即在不关闭数据库的情况下,对数据库进行 ...
- 深入理解 Spring 事务原理
本文由码农网 – 吴极心原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划! 一.事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供 ...
- 深入理解 Spring 事务原理【转】
本文转自码农网 – 吴极心原创 连接地址:http://www.codeceo.com/article/spring-transactions.html 一.事务的基本原理 Spring事务的本质其 ...
- MySQL事务原理&实战【官方精译】
事务隔离级别 事务隔离是数据库处理的基础之一.隔离是I中的首字母 ACID ; 隔离级别是在多个事务同时进行更改和执行查询时,对结果的性能和可靠性,一致性和可重复性之间的平衡进行微调的设置. Inno ...
- Flink 集群运行原理兼部署及Yarn运行模式深入剖析
1 Flink的前世今生(生态很重要) 原文:https://blog.csdn.net/shenshouniu/article/details/84439459 很多人可能都是在 2015 年才听到 ...
- java事务 深入Java事务的原理与应用
一.什么是JAVA事务 通常的观念认为,事务仅与数据库相关. 事务必须服从ISO/IEC所制定的ACID原则.ACID是原子性(atomicity).一致性(consistency).隔离性 (iso ...
- spring事务-说说Propagation及其实现原理
前言 spring目前已是java开发的一个事实标准,这得益于它的便利.功能齐全.容易上手等特性.在开发过程当中,操作DB是非常常见的操作,而涉及到db,就会涉及到事务.事务在平时的开发过程当中,就算 ...
随机推荐
- git分支管理一
1.创建本地分支 local_branch git branch local_branch 2.创建本地分支local_branch 并切换到local_branch分支 git checkout - ...
- iOS.ReactNative-5-make-react-native-to-support-dynamically-update
基于React Native来实现App的热更新 热更新: 类似Hot-Patching,在程序不发布版本的前提下,对部分功能或者全部功能进行修改或者升级. JSX 1. JSX简介 1.1 http ...
- 关于Linkedlist 和 ArrayDeque的讨论
转自:http://blog.csdn.net/f2006116/article/details/51375470 其中:我们要讨论的LinkedList和ArrayDeque都是实现Deque接口, ...
- 3G产品升级相关知识
1.3G产品升级时,内核,文件系统,boot,应用程序,全都升级了,是在boot里升的; 2.拨号模式里的 chap:公网; pap:专网 3.用来查看U盘挂在哪个目录下: cat /proc/par ...
- 清空stringbuilder
大家知道对于字符串频繁拼接是使用stringbuilder.Append方法比使用string+=方法效率高很多,但有时需要清空stringbuilder时却不知道怎么清空,因为它没有clear或em ...
- seaJS 简单例子,理解seaJS
学习心得: 记得第一次学underscore的时候,去的官网(不管什么都是官网好),呼啦一长列语法,我就一个个看,看完也不知道underscore是做什么的.就是现在underscore我也用不上,学 ...
- 提高代码质量 CheckStyle FindBugs PMD
提高代码质量-工具篇 注:这是一篇翻译文章,原文:How to improve quality and syntax of your Android code,为了理解连贯,翻译过程中我修改了一些陈述 ...
- screenX、clientX、pageX的区别
screenX:鼠标位置相对于用户屏幕水平偏移量,而screenY也就是垂直方向的,此时的参照点也就是原点是屏幕的左上角. clientX:跟screenX相比就是将参照点改成了浏览器内容区域的左上角 ...
- js数组去重的三种方法
<script type="text/javascript"> /*// 第一种冒泡法删除 var arr=[1,2,2,78,3,456,456]; for(var ...
- Object-C中一些不同于C系列语言表现的特性
这段时间体验和学习OC,虽然这么多年基本都在使用C系列语言(C,C++,C#),但是仍然有很多的不习惯. 当然,这些不习惯不代表讨厌或者不好,也许这些就是OC作为Apple开发首选语言而显得特殊的一些 ...