mysql的两阶段协议(封锁定理,虫洞事务)
我们都知道数据库的事务具有ACID的四个属性:原子性,一致性,隔离性和持久性。然后在多线程操作的情况下,如果不能保证事务的隔离性,就会造成数据的修改丢失(事务2覆盖了事务1的修改结果)、读到脏数据(事务2读到了事务1未回滚的数据)、不可重读(事务2读到了事务1未提交的修改)和幻读(事务2读到了事务1未提交的增删)等。保证事务隔离性可以防止事务出现以上问题,那么数据库又是怎么来保证事务的隔离性的呢?
mysql使用两阶段协议来保证事务执行的串行化从而保证事务的隔离性的。
首先,为了保证数据访问的串行,每个数据资源都有对应的锁(mysql的锁只细化到行级),那么只要保证每个数据资源的访问都是串行化的,然后整个数据库不就可以保证每个数据操作之间的隔离性了么,就是说:
只要每个数据操作都有对应的锁覆盖,然后把每个操作都加上对应的锁,这样可以保证事务执行的串行化么?
答案是:可以保证,但是有个前提是每个事务只包含对一个数据的操作。事实上mysql也默认是这样做的:如果用户没有手动开启事务,那么根据AUTOCOMMIT机制,mysql默认将每一个数据库操作封装成一个事务来处理。
然而实际情况中,很多时候一个事务不只包含一个数据库操作,比如电商平台在生成订单时,一个事务里包含了对订单表、用户表、商品表等的操作。在多线程操作的情况下,如果只用数据库的锁来保证的话,就会出现上面所提到的一些数据异常情况。这时候就需要两阶段协议来保证事务的隔离性了。那么进入今天的主题:
两阶段协议如何保证多事务操作之间的隔离性?
上面说过,只要事务执行是串行的,事务之间就是隔离的,在网上搜索两阶段协议为何能保证串行化,只搜到一个封锁定理:如果事务是良构的且是两阶段的,那么任何一个合法的调度都是可串行化的。 既然是定理,那一定是严格成立且可证明的,于是顺藤摸瓜,找到了封锁定理的证明(<事务处理:概念与技术>>这本书的7.5.8.2节)。
首先我们解析命题:
条件:良构的事务、两阶段、合法的调度
结论:是可串行化的。
在书上找到条件的描述:
如果事务的每个READ、WRITE、 UNLOCK都被响应的锁覆盖,且所有的锁都是在事务结束时释放,那么称这样的事物是良构的。(mysql的表和行数据在被操作时,都有对应的锁覆盖)
如果一个事务可以分成两个阶段,只请求封锁的扩展阶段和只释放锁的收缩阶段,那么称之为两阶段的事务。(mysql采用两阶段封锁协议)
调度是一组事务的操作的某种合并结果。(mysql支持多事务并行执行)
一个调度是合法的,如果同一时间没发生两个不同事务的锁冲突。(mysql需要保证并行事务不冲突)
因为每个事务T都是良构的,所以必定对应着一个解锁操作Unlock,事务T的解锁操作步骤在调度中的索引为St。
假设在调度中事务T1在事务T2之前执行,T1<<<T2,则事务T2依赖事务T1,使得事务T1对对象O的操作步骤a1在事务T2对对象O的操作步骤a2之前,那么a1和a2必定有一个步骤对象O正覆盖着排他锁(WRITE)(因为如果是两个挨着的读事务(READ)不存在依赖关系,所以他们的执行顺序没有明确的等价执行序列),如果是a1时对象O覆盖着一个XLOCK(排他锁),a2时对象O应该覆盖着一个SLOCK(共享锁)或XLOCK(排他锁),与前面的XLOCK互斥,又由于是两阶段的,所以在a1和a2之间,会存在一个事务T1给对象O解锁的Unlock操作步骤St1,事务T2的解锁操作步骤St2在a2之后,所以有:St1<<<St2,即事务T1的解锁在事务T2的解锁之前。同理在a2是WRITE操作的时候也成立。如果调度是不可串行化的,那么必然存在T1<<<T2时,St2<<<St1,与上述结论矛盾,所以:
如果一个调度包含的事物都是良构的且为两阶段的,那么该调度是可串行化的。
可能有人会问,为什么不给每个事务加排他锁来保证多事务执行的串行化呢?
是因为如果把读锁也定义为排他锁的话,会大大的降低并发读的效率,而查询操作在数据库的操作中占了很大的比例,所以mysql默认采用的可重复读的隔离级别,用两阶段协议和全场景覆盖的锁来保证执行结果的串行化,并没有采用全用排他锁来保证串行化。
mysql的两阶段协议(封锁定理,虫洞事务)的更多相关文章
- 使用golang理解mysql的两阶段提交
使用golang理解mysql的两阶段提交 文章源于一个问题:如果我们现在有两个mysql实例,在我们要尽量简单地完成分布式事务,怎么处理? 场景重现 比如我们现在有两个数据库,mysql3306和m ...
- MySQL binlog 组提交与 XA(两阶段提交)
1. XA-2PC (two phase commit, 两阶段提交 ) XA是由X/Open组织提出的分布式事务的规范(X代表transaction; A代表accordant?).XA规范主要定义 ...
- MySQL binlog 组提交与 XA(分布式事务、两阶段提交)【转】
概念: XA(分布式事务)规范主要定义了(全局)事务管理器(TM: Transaction Manager)和(局部)资源管理器(RM: Resource Manager)之间的接口.XA为了实现分布 ...
- MySQL binlog 组提交与 XA(两阶段提交)--1
参考了网上几篇比较靠谱的文章 http://www.linuxidc.com/Linux/2015-11/124942.htm http://blog.csdn.net/woqutechteam/ar ...
- 聊一聊 MySQL 中的数据编辑过程中涉及的两阶段提交
MySQL 数据库中的两阶段提交,不知道您知道不?这篇文章就简单的聊一聊 MySQL 数据库中的两阶段提交,两阶段提交发生在数据变更期间(更新.删除.新增等),两阶段提交过程中涉及到了 MySQL 数 ...
- 全网最牛X的!!! MySQL两阶段提交串讲
目录 一.吹个牛 二.事务及它的特性 三.简单看下两阶段提交的流程 四.两阶段写日志用意? 五.加餐:sync_binlog = 1 问题 六.如何判断binlog和redolog是否达成了一致 七. ...
- flink-----实时项目---day07-----1.Flink的checkpoint原理分析 2. 自定义两阶段提交sink(MySQL) 3 将数据写入Hbase(使用幂等性结合at least Once实现精确一次性语义) 4 ProtoBuf
1.Flink中exactly once实现原理分析 生产者从kafka拉取数据以及消费者往kafka写数据都需要保证exactly once.目前flink中支持exactly once的sourc ...
- MySQL两阶段提交
参数介绍 innodb_flush_log_at_trx_commit 0: 每隔1s,系统后台线程刷log buffer,也就是把redo日志刷盘,这里会调用fsync,所以可能丢失最后1s的事务. ...
- 关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究 转载
1.XA XA是由X/Open组织提出的分布式事务的规范.XA规范主要定义了(全局)事务管理器(Transaction Manager)和(局部)资源管理器(Resource Manager)之间的接 ...
随机推荐
- Birt报表
研究了两天终于发现开始学会了BIRT报表的开发流程. 第一步:到http://www.eclipse.org/downloads/下载 Eclipse IDE for Java and Report ...
- L1与L2正则化的对比及多角度阐述为什么正则化可以解决过拟合问题
正则化是一种回归的形式,它将系数估计(coefficient estimate)朝零的方向进行约束.调整或缩小.也就是说,正则化可以在学习过程中降低模型复杂度和不稳定程度,从而避免过拟合的危险. 一. ...
- python 快速发送大量邮件
因为公司需求,需要发送千万封级别邮件. # coding:utf-8 import csv import smtplib from email.mime.text import MIMEText im ...
- 使用Rider中搭建specflow+xunit+selenium对web页面进行自动化功能测试环境
运行rider,创建测试解决方案,选择xunit,点击create创建 导入包,由于本人使用chrome浏览器(需先下载好对应的浏览器驱动),所以导入了selenium.webdriver.c ...
- python06-列表表达式、生成器表达式及其面试题、解耦简单介绍、函数递归相关
目录: 一.列表推导式 二.生成器表达式 三.集合生成器 四.生成器面试题 五.解耦简单介绍 六.函数递归相关 一.列表推导式 需求:将[1,3,5]中的每个元素平方 正常思路: new_list = ...
- 【微信小程序】踩坑指南(持续更新)
前言 说明: 基于mpvue框架:mpvue官方文档 语法同vue框架:vue官方文档 小程序中会有一些坑点,这里会就工作中遇到的坑一一列举出来 无说明时请直接看代码注释 v-show无法使用在小程序 ...
- 力扣(LeetCode)键盘行 个人题解
给定一个单词列表,只返回可以使用在键盘同一行的字母打印出来的单词.键盘如下图所示. 示例: 输入: ["Hello", "Alaska", "Dad& ...
- boost.asio新框架的设计概念总结
1.66版本,boost.asio库重新设计了框架,目前最新版为1.71.读了几天代码后,对框架中相关概念总结.因为是泛型编程的库,所以分析的概念层的设计. 可通过boost官方文档,strand的1 ...
- B0宏
在编译android平台用的ffmpeg时,抛出这样一个错误: 这句代码怎么看都找出有毛病,为什么B0会报错? 翻看aaccoder.c,也没有发现问题.为什么B0就成了一个常量数字,这里只有一个可能 ...
- 原创|我是如何从零学习开发一款跨平台桌面软件的(Markdown编辑器)
原始冲动 最近一直在学习 Electron 开发桌面应用程序,目的是想做一个桌面编辑器,虽然一直在使用Typore这款神器,但无奈Typore太过国际化,在国内水土不服,无法满足我的一些需求. 比如实 ...