MySql-两阶段加锁协议
此篇博客主要是讲述MySql(仅限innodb)的两阶段加锁(2PL)协议,而非两阶段提交(2PC)协议,区别如下:
2PL,两阶段加锁协议:主要用于单机事务中的一致性与隔离性。
2PC,两阶段提交协议:主要用于分布式事务。
MySql本身针对性能,还有一个MVCC(多版本控制)控制,本文不考虑此种技术,仅仅考虑MySql本身的加锁协议。
什么时候会加锁
在对记录更新操作或者(select for update、lock in share model)时,会对记录加锁(有共享锁、排它锁、意向锁、gap锁、nextkey锁等等),本文为了简单考虑,不考虑锁的种类。
什么是两阶段加锁
在一个事务里面,分为加锁(lock)阶段和解锁(unlock)阶段,也即所有的lock操作都在unlock操作之前,如下图所示:
为什么需要两阶段加锁
引入2PL是为了保证事务的隔离性,即多个事务在并发的情况下等同于串行的执行。 在数学上证明了如下的封锁定理:
如果事务是良构的且是两阶段的,那么任何一个合法的调度都是隔离的。
具体的数学推到过程可以参照<<事务处理:概念与技术>>这本书的7.5.8.2节.
此书乃是关于数据库事务的圣经,无需解释(中文翻译虽然晦涩,也能坚持读下去,强烈推荐)
工程实践中的两阶段加锁-S2PL
在实际情况下,SQL是千变万化、条数不定的,数据库很难在事务中判定什么是加锁阶段,什么是解锁阶段。于是引入了S2PL(Strict-2PL),即:
在事务中只有提交(commit)或者回滚(rollback)时才是解锁阶段,
其余时间为加锁阶段。
如下图所示:
这样的话,在实际的数据库中就很容易实现了。
两阶段加锁对性能的影响
上面很好的解释了两阶段加锁,现在我们分析下其对性能的影响。考虑下面两种不同的扣减库存的方案:
方案1:
begin;
// 扣减库存
update t_inventory set count=count-5 where id=${id} and count >= 5;
// 锁住用户账户表
select * from t_user_account where user_id=123 for update;
// 插入订单记录
insert into t_trans;
commit;
方案2:
begin;
// 锁住用户账户表
select * from t_user_account where user_id=123 for update;
// 插入订单记录
insert into t_trans;
// 扣减库存
update t_inventory set count=count-5 where id=${id} and count >= 5;
commit;
由于在同一个事务之内,这几条对数据库的操作应该是等价的。但在两阶段加锁下的性能确是有比较大的差距。两者方案的时序如下图所示:
由于库存往往是最重要的热点,是整个系统的瓶颈。那么如果采用第二种方案的话,
tps应该理论上能够提升3rt/rt=3倍。这还仅仅是业务就只有三条SQL的情况下,
多一条sql就多一次rt,就多一倍的时间。
值得注意的是:
在更新到数据库的那个时间点才算锁成功
提交到数据库的时候才算解锁成功
这两个round_trip的前半段是不会计算在内的
如下图所示:
当前只考虑网络时延,不考虑数据库和应用本身的时间消耗。
依据S2PL的性能优化
从上面的例子中,可以看出,需要把最热点的记录,
放到事务最后,这样可以显著的提高吞吐量。更进一步:
越热点记录离事务的终点越近(无论是commit还是rollback)
笔者认为,先后顺序如下图:

避免死锁
这也是任何SQL加锁不可避免的。上文提到了按照记录Key的热度在事务中倒序排列。 那么写代码的时候任何可能并发的SQL都必须按照这种顺序来处理,不然会造成死锁。如下图所示: 
select for update和update where 谓词计算
我们可以直接将一些简单的判断逻辑写到update的谓词里面,以减少加锁时间,考虑下面两种方案:
方案1:
begin:
int count = select count from t_inventory for update;
if count >= 5:
update t_inventory set count=count-5 where id =123
commit
else
rollback
方案2:
begin:
int rows = update t_inventory set count=count-5 where id =123 and count >=5
if rows > 0:
commit;
ele
rollback;
时延如下图所示: 
可以看到,通过在update中加谓词计算,少了1rt的时间。
由于update在执行过程中对符合谓词条件的记录加的是和select for update一致的排它锁
(具体的锁类型较为复杂,不在这里描述),所以两者效果一样。
总结
MySql采用两阶段加锁协议实现隔离性和一致性,我们只有深入的去理解这种协议,才能更好的对我们的SQL进行优化,增加系统的吞吐量。
MySql-两阶段加锁协议的更多相关文章
- 全网最牛X的!!! MySQL两阶段提交串讲
目录 一.吹个牛 二.事务及它的特性 三.简单看下两阶段提交的流程 四.两阶段写日志用意? 五.加餐:sync_binlog = 1 问题 六.如何判断binlog和redolog是否达成了一致 七. ...
- MySQL两阶段提交
参数介绍 innodb_flush_log_at_trx_commit 0: 每隔1s,系统后台线程刷log buffer,也就是把redo日志刷盘,这里会调用fsync,所以可能丢失最后1s的事务. ...
- mysql的两阶段协议(封锁定理,虫洞事务)
我们都知道数据库的事务具有ACID的四个属性:原子性,一致性,隔离性和持久性.然后在多线程操作的情况下,如果不能保证事务的隔离性,就会造成数据的修改丢失(事务2覆盖了事务1的修改结果).读到脏数据(事 ...
- 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源码之两阶段提交
在双1的情况下,两阶段提交的过程 环境准备:mysql 5.5.18, innodb 1.1 version配置: sync_binlog=1 innodb_flush_log_at_trx_comm ...
- centos lamp/lnmp阶段复习 以后搬迁discuz论坛不需要重新安装,只需修改配置文件即可 安装wordpress 安装phpmyadmin 定时备份mysql两种方法 第二十五节课
centos lamp/lnmp阶段复习 以后搬迁discuz论坛不需要重新安装,只需修改配置文件即可 安装wordpress 安装phpmyadmin 定时备份mysql两种方法 第二十五节 ...
- 聊一聊 MySQL 中的数据编辑过程中涉及的两阶段提交
MySQL 数据库中的两阶段提交,不知道您知道不?这篇文章就简单的聊一聊 MySQL 数据库中的两阶段提交,两阶段提交发生在数据变更期间(更新.删除.新增等),两阶段提交过程中涉及到了 MySQL 数 ...
随机推荐
- 直接执行SQL语句的快捷键是什么啊?嘎嘎
在查询中输入SQL语句后,执行语句的快捷键~ 分享到: 2009-10-23 10:59网友采纳 左键..嘿嘿,开个玩笑 你把鼠标移动到执行按钮上停一会就能看到了啊
- JAVA 综合面试题
JAVA 综合面试题 2007-08-12 目录 TOC \o "1-3" \h \z \u Java面试题整理 9 Java面向对象 9 1. super()与this()的区别 ...
- python的logging模块之读取yaml配置文件。
python的logging模块是用来记录应用程序的日志的.关于logging模块的介绍,我这里不赘述,请参见其他资料.这里主要讲讲如何来读取yaml配置文件进行定制化的日志输出. python要读取 ...
- Day17 Django的基础使用和结构
整个Django的访问流程: 浏览器 urls: http://127.0.0.1:8000/timer url.py: 1, http://127.0.0.1:8000/timer GET 无请求数 ...
- Django 2.0 Release note阅读简记
最前面就是大家都知道的这个版本开始只支持py3.4+,而且下一个大版本就不支持3.4,再就是建议所有插件开始放弃1.11 1.最惊艳的变化,就是URL配置正则表达式的简化,旧的: url(r'^art ...
- OO,OO以后,及其极限
1.什么是软件开发? 软件开发的过程就是人们使用各种计算机语言将人们关心的现实世界映射到计算机世界的过程: 现在的计算机的数学理论基础是由计算机的开山鼻祖,大名鼎鼎的图灵于1937年提出的图灵机模型. ...
- HTML Meta信息的优先级
一般来讲meta的信息都是不同维度的不会有冲突,不过下面两个有一定冲突: <meta name="renderer" content="webkit"&g ...
- Android开发阅读文档资源
Android Studio:工具:http://developer.android.com/intl/zh-cn/tools/studio/index.html培训教程:http://develop ...
- Java开源生鲜电商平台-系统简介
Java开源生鲜电商平台-系统简介 1.生鲜电商平台的价值与定位. 生鲜电商平台是一家致力于打造全国餐饮行业智能化.便利化.平台化与透明化服务的创新型移动互联网平台,连接买家与卖家之间的一个平台 看以 ...
- webService(一)开篇
Webservice技术在web开发中算是一个比较常见技术.这个对于大多数的web开发者,别管是Java程序员还是.NET程序员应该都不是很陌生.今天我就和大家一起来学习一下webservice的基本 ...