美文网首页
mysql锁的简单想法(不确定对不对)

mysql锁的简单想法(不确定对不对)

作者: wncbbnk | 来源:发表于2017-11-02 23:18 被阅读0次

1. 隔离级别

1. read uncommitted

事务可以看见其他未提交事务的修改。会导致脏读。

2. read committed

事务只能看见其他提交事务的修改。但是如果事务A读取一批数据set,其他事务之后修改了这个数据set并提交(此时事务A没有提交),这时事务A再读取数据set就跟第一次读取的结果不一致。会导致不可重复读。

3. repeatable read

在事务执行过程中,重复读到的数据是一致的

4. serializable

2. 问题

1. 脏读

事务A读到了事务B未提交的数据。(read uncommitted)

2. 不可重复读

事务A第一次读取行num,此时事务B修改行num并提交,事务A再读行num,数据会发生变化。(read uncommitted, read committed)

3. 幻读

事务A第一次查询范围query_range,返回n行,此时事务B在该查询范围内插入了一行数据并提交,事务A再次查询范围query_range会看到B插入的数据。(read uncommitted, read committed, repeatable read)

The so-called phantom problem occurs within a transaction when the same query produces different sets of rows at different times. For example, if a SELECT is executed twice, but returns a row the second time that was not returned the first time, the row is a “phantom” row.

在同一个事务执行过程中,两次相同的查询,但是查询的返回数据行数不同。

隔离级别 脏读 不可重复读 幻读
read uncommitted yes yes yes
read committed no yes yes
repeatable read no no yes
serializable no no no

3. Innodb 行锁算法

1. record lock 锁住某一行

2. gap lock 锁住两行之间的间隙(不包括行本身)

3. next key lock 同时应用1,2

4. 实例

0. current read, snapshot read

1. 实例1

  • 隔离级别 repeatable read
  • 数据库 mysql innodb
CREATE TABLE `test_lock` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
mysql> select * from test_lock;
+----+------+
| id | a    |
+----+------+
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
|  4 |    4 |
|  5 |    5 |
|  6 |    6 |
+----+------+
6 rows in set (0.00 sec)

开启sessionA, sessionB

sessionA> begin;
Query OK, 0 rows affected (0.01 sec)

sessionA> delete from test_lock where a=3;
Query OK, 1 row affected (0.00 sec)

sessionA>

此时锁(行锁、gap锁)的情况如下图,标红为加锁,采用next key lock。(不光在索引a上加锁,索引a中3所对应的主键索引也会加锁,只画了索引a)
注意:这里是主键索引的顺序与a索引的顺序一致的情况。一致的情况下,新插入的4会插入在原来的4之后。我们定义函数index_key(x), 表示获取x所对应的主键索引,new(x)表示新插入的x,old(x)表示已经存在的x。如果index_key(old(4))>index_key(new(4)),那新的4是插不进去的,因为新的4会被放在老的4的前面。同理,新插入的2也有可能插入进去(只要index_key(new(2))<index_key(old(2)))。具体的例子整理后发出

lock.png

对于sessionB,插入2,3失败,插入4成功。(如图lock.png,新插入的2会被2与3之间gap锁阻止,新插入的3肯定失败,但是新插入的4就没问题)

sessionB> insert into test_lock(a) values(2);
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted
sessionB> insert into test_lock(a) values(3);
^C^C -- query aborted
ERROR 1317 (70100): Query execution was interrupted
sessionB> insert into test_lock(a) values(4);
Query OK, 1 row affected (0.00 sec)

2. 实例2

  • 隔离级别 repeatable read
  • 数据库 mysql innodb
    验证实例1的另一种情况。
CREATE TABLE `test_lock` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
mysql> select * from test_lock2;
+----+------+
| id | a    |
+----+------+
|  1 |    1 |
|  5 |    3 |
|  3 |    5 |
|  7 |    7 |
+----+------+
6 rows in set (0.00 sec)

开启sessionA:

sessionA> begin;
sessionA> delete from test_lock2 where a=5;

这个时候情况如下图所示:


image.png

如果按照实例1的分析,不看主键索引id,应该插入(id=4,a=3)应该会被gap锁锁定,但是事实是可以插入成功。因为插入的(i4=d,a=3)放在了(id=5,a=3)的上面。
同样的道理,不看主键索引id,通过实例1的分析,插入(id=6,a=7)应该可以插入,但是事实不行,因为(id=6,a=7)被a=5与a=7之间的gap锁阻止了。
新插入的(id=4, a=3),需要判断会插入在(id=5, a=3)之前还是之后,很明显之前(4<5),那么(id=3, a=5)与(id=5, a=3)之间的gap锁不会阻止。
新插入的(id=6, a=7),需要判断会插入在(id=7, a=7)之前还是之后,很明显之前(6<7),那么(id=6, a=7)会被(id=3, a=5)与(id=5, a=3)与(id=7, a=7)之间的gap锁阻止。

5.TODOLIST

1. 在普通索引相同、主键索引不同(废话)的情况下,order by普通索引,顺序是一定按照主键索引的顺序返回吗?(测试是这样,真要搞清楚还是要看代码)

相关文章

  • mysql锁的简单想法(不确定对不对)

    1. 隔离级别 1. read uncommitted 事务可以看见其他未提交事务的修改。会导致脏读。 2. re...

  • MySQL表级锁和行级锁

    MySQL学习笔记(五):MySQL表级锁和行级锁 一:概述 相对其他数据库而言,MySQL的锁机制比较简单,其最...

  • MySQL的锁机制

    MySQL锁简介 MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。比如,MyISAM和...

  • mysql锁机制

    mysql锁机制深层而又复杂,而且针对不对的存储引擎锁实现的方式以及表现形式又不一样,本文只针对mysqlInno...

  • 13.MySQL锁机制

    MySQL锁 相对于其他的数据库而言,MySQL的锁机制比较简单,最显著的特点就是不同的存储引擎支持不同的锁机制。...

  • MySQL学习

    MySQL锁概述 相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。...

  • MySQL解锁与锁表

    MySQL锁概述 相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。...

  • Mysql的锁

    MySql锁的分类 Mysql里的锁大致可以分为全局锁、表级锁和行锁三类。 全局锁 Mysql 增加全局锁的方法:...

  • mysql锁的简单理解

    一.锁 我们通常概念里的锁,是用来处理线程安全问题,锁(latch)的对象是线程,而在mysql中通常所说的锁(l...

  • MySQL二进制日志

    MySQL-day10 MySQL存储引擎-锁 1)什么是“锁”? 2)“锁”的作用是什么? 3)MySQL中的锁...

网友评论

      本文标题:mysql锁的简单想法(不确定对不对)

      本文链接:https://www.haomeiwen.com/subject/xzfzpxtx.html