最近买了《高性能MySQL》这本书回来看,从中收益颇多!我来一吐为快!

我们都知道事务,那么在什么情况下我们需要使用事务呢?

银行应用是解释事务的一个经典例子。假设一个银行的数据库有两张表:支票(checking)和储蓄(savings)表。现在johnson要从支票账户中转移200块大洋到储蓄表中,那么至少需要三个步骤:

  1. 检查支票账户余额是否高于200块大洋
  2. 支票账户减少200块大洋
  3. 储蓄账户中增加200块大洋

试想一下,如果上面步骤执行到第二步,突然因为什么原因而终止了,顾客支票账户中莫名其妙的减少了200块大洋。如果顾客恰好是一位情绪激动的大妈,那你就等着大妈带着平底锅和四级头去银行找你吧!

所以为了避免这种情况,就必须用到事务,上述三个步骤中有任何一个执行失败,就必须回滚所有的步骤,以免有大妈找上门。事务SQL如下所示:

  1. START TRANSACTION;
  2. SELECT balance FROM checking WHERE customer_id=123456;
  3. UPDATE checking SET balance = balance - 200 WHERE customer_id=123456;
  4. UPDATE savings SET balance = balance + 200 WHERE customer_id=123456;
  5. COMMIT;

事务之所以可靠,当然离不开ACID特性:

  • 原子性(atomicity):整个事务中的操作要么全部成功,要么全部失败。
  • 一致性(consistency):数据库总是从一个一致性状态转换到另一个一致性状态。比如上面所说的,事务开始前和执行后,顾客johnson在银行的总账户余额是一样的。
  • 隔离性(isolation):通常来说,一个事务所做的修改在提交之前,其他事务是不可见的。也就是说事务间是相互隔离的。
  • 持久性(durability):事务在提交之后,对数据库数据所做的修改是永久性的。

细心的人可能会注意到。在讨论隔离性的时候,我用了“通常来说”,下面就让我们讨论下事务的隔离级别。

隔离级别 脏读可能性 不可重复读可能性 幻读可能性 加锁读
READ UNCOMMITTED YES YES YES NO
READ COMMITTED NO YES YES NO
REPEATABLE READ NO NO YES NO
SERIALIZABLE NO NO NO YES
  • 未提交读(READ UNCOMMITTED):事务中的修改,即使没有提交,其他事务也可以读到,这就有可能造成了脏读。
  • 提交读(READ COMMITTED):大多数数据库系统默认实用的隔离级别就是这种,但mysql不是。READ COMMITTED就是在事务提交前,所做的修改对其他事务是不可见的。但READ COMMITTED可能会造成不可重复读。就是在一个事务中,同样的查询语句,可能会得到不一样的结果。其实就是在两次查询中间,另一个事务修改了查询结果的值。
  • 可重复读(REPETABLE READ):REPETABLE READ解决了脏读和不可重复读的问题,但理论上,REPETABLE READ无法解决幻读的问题。幻读就是指,一个事务在读取某一范围的值时,另一个事务恰好在该范围内插入了新纪录,那么当你再次读取该范围的值时,就会产生幻行。这与不可重复读有点像,只不过不可重复读时UPDATE,而幻读时INSERT
  • 可串行化(SERIALIZABLE):SERIALIZABLE读取每一行数据都要加锁,强制事务串行执行,所以可能导致大量的超时和锁争用问题。

到这里,如果还不是太懂,你需要细细消化下前面的内容,这时可以打开mysql,将隔离级别设置为READ COMMITTED。然后试试它是不是解决了脏读,会不会出现不可重复读?再将隔离级别设置为REPETABLE READ。看看REPETABLE READ是不是解决了不可重复读,会不会出现幻读?

SET session transaction isolation level read committed;

如果你真的实验了,会发现mysql的REPETABLE READ隔离级别并不会出现幻读的现象。那你有没有想过mysql的事务是怎么实现的呢?

你肯定听说mysql的表锁和行锁,那你可能以为事务是基于行锁实现的。其实并没有那么简单,为了提高并发性能,mysql的大多是事务引擎都同时实现了多版本并发控制(MVCC)。它在很多情况下避免了加锁操作,所以开销更低。MVCC大都实现了非阻塞的读操作,写操作也只锁定必要的行。

那么InnoDB中的MVCC是如何工作的呢?其实是通过在每行数据后面增加两个列,一个是创建版本号,一个是删除版本号。里面存储的是系统版本号,你开启一个事务系统版本号就会递增。事务开始时刻的系统版本号就作为事务版本号,用来和查询的每行记录的版本号做比较。下面看下REPETABLE READ隔离界别下,MVCC具体是如何操作的。

  • SELECT查询出的数据需要满足2个条件    1、创建版本号 <= 系统版本号  2、删除版本号为空或删除版本号>系统版本号
  • INSERT     为新插入的每一行保存当前事务版本号为行的创建版本号
  • UPDATE  为插入的一行新记录保存当前事务版本号为行的创建版本号,同时保存当前事务版本号为原来的行的删除版本号
  • DELETE  为删除的每一行保存当前事务版本号为行的删除版本号

保存这两个额外的系统版本号,可以使大多数读操作都不用加锁,这样性能就会更好。但需要额外的存储空间和一些额外的检查工作,这也相当于用空间换时间。

在某些情况下我们还是需要用的锁。InnoDB采用两段锁协议。在事务执行过程中随时都可以加锁,事务提交或回滚时同时释放所有锁。这些锁一般都是隐式锁定,InnoDB会根据需要自动加锁。当然,你也可以通过SQL语句自己加锁:

SELECT ..... LOCK IN SHARE MODE;     乐观锁
SELECT ..... FOR UPDATE; 悲观锁

个人建议,除非你明确知道自己在干什么,否则轻易不要显式加锁,只会事倍功半!!!

高性能MySQL--innodb中事务的隔离级别与锁的关系的更多相关文章

  1. mysql innodb引擎事务的隔离级别

    一.事务的基本要素(ACID) 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节.事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有 ...

  2. 重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系

    重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系 Innodb中的事务隔离级别和锁的关系 前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁 ...

  3. Innodb中的事务隔离级别和锁的关系(转载)

    nodb中的事务隔离级别和锁的关系 原文:https://tech.meituan.com/innodb-lock.html ameng ·2014-08-20 15:50 前言: 我们都知道事务的几 ...

  4. 【转载】Innodb中的事务隔离级别和锁的关系

    前言 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所 ...

  5. Mysql数据库事务的隔离级别和锁的实现原理分析

    Mysql数据库事务的隔离级别和锁的实现原理分析 找到大神了:http://blog.csdn.net/tangkund3218/article/details/51753243 InnoDB使用MV ...

  6. Hibernate中事务的隔离级别设置

    Hibernate中事务的隔离级别,如下方法分别为1/2/4/8. 在Hibernate配置文件中设置,设置代码如下

  7. MySQL InnoDB中的事务隔离级别和锁的关系

    前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力. ...

  8. Innodb中的事务隔离级别和锁的关系

    前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力. ...

  9. Innodb中的事务隔离级别和锁的关系(转)

    原文:http://tech.meituan.com/innodb-lock.html 前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库 ...

随机推荐

  1. c# 修改winform中app.config的配置值

    public bool ChangeConfig(string AppKey,string AppValue) { bool result = true; try { XmlDocument xDoc ...

  2. SQL Server ->> 时间函数: EOMONTH, DATEFROMPARTS, TIMEFROMPARTS, DATETIMEFROMPARTS, DATETIMEOFFSETFROMPARTS

    上面几个函数都是SQL Server 2012新增的时间函数. EOMONTH 返回传入时间的月结束日,返回数据类型为DATE SELECT EOMONTH(GETDATE()) 结果为 DATEFR ...

  3. 纯CSS画的基本图形

    图形包括基本的矩形.圆形.椭圆.三角形.多边形,也包括稍微复杂一点的爱心.钻石.阴阳八卦等.当然有一些需要用到CSS3的属性,所以在你打开这篇文章的时候,我希望你用的是firefox或者chrome, ...

  4. Python学习---基础函数的学习

    1.1. 基础函数 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可. 灌输一个概念:Python中函数就是对象,函数和我们之前的[1,2,3],'abc ...

  5. Python学习---重点模块之xml

    xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单 数据准备 <?xml version="1.0"?> <data&g ...

  6. 大数据学习---大数据的学习【all】

    大数据介绍 什么是大数据以及有什么特点 大数据:是指无法在一定时间内用常规软件工具对其内容进行抓取.管理和处理的数据集合. 大数据是一种方法论:“一切都被记录,一切都被数字化,从数据中寻找需求,寻找知 ...

  7. cmd:相关命令和笔记

    (1)查看git版本:git --version (2)

  8. (名词 形容词 动词 副词)重读&(冠词 介词 连词 代词 辅助词(Be))弱读

    二,一些发音规则 除了上面的练习之外,这里还有几个注意点需要我们有足够的认识,那就是英语有重读.弱读.连读.爆破.语感(节奏和断句)等(其实当你跟读并背诵新概念之后,这一切都是神马,你不知觉地也会发现 ...

  9. postgresql+postgis+pgrouting实现最短路径查询(2)---openlayers+geoserver实现最短路径

    自己的最短路径实现基本上是按照参考博文的1.2和3进行的,实现的时候也是问题不断,只能是一个一个解决. 问题1:自己发布的geoserver服务无法和OSM底图叠加到一起. 解决:参考博文2提到发布服 ...

  10. 【Hankson 的趣味题】

    可能我只适合这道题的50分 但还是要争取一下的 我们知道对于\(gcd\)和\(lcm\)有这样的定义 \(a=\prod _{i=1}^{\pi(a)}p_i^{d_{i}}\) \(b=\prod ...