MySQL文档翻译:幻影行

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.

所谓的幻影读问题是在同一个事务内两次执行一个相同的查询,最终查询到的结果不一致。举个例子,如果一个 select 执行两次,第二次的查询结果返回了一行第一次查询所没有返回的结果,就说这行数据是一行「幻影」。

Suppose that there is an index on the id column of the child table and that you want to read and lock all rows from the table having an identifier value larger than 100, with the intention of updating some column in the selected rows later:

1
SELECT * FROM child WHERE id > 100 FOR UPDATE;
Read more

MySQL一例锁分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
show create table banner;
CREATE TABLE `banner` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '元素ID',
`name` varchar(20) NOT NULL COMMENT '元素名称',
`city` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=utf8;

mysql> select * from banner;
+----+------+------+
| id | name | city |
+----+------+------+
| 3 | a | 2 |
| 33 | xx | 1 |
| 34 | xx | 1 |
| 35 | xx | 1 |
| 36 | a4 | 1 |
| 37 | a4 | 1 |
| 38 | a4 | 0 |
| 41 | a | 0 |
+----+------+------+
Read more

如何查看MySQL加锁状态

information_schema.innodb_locks

这个表罗列了两类锁:

  • 事务请求了但是还没有获取到的锁
  • 事务持有的锁,并且这个锁阻塞了其他事务的执行

The INNODB_LOCKS table contains information about each lock that an InnoDB transaction has requested but not yet acquired, and each lock that a transaction holds that is blocking another transaction.

Read more

间隙锁和一些引申

最近在研究数据库的事务和并发控制,顺带把以前碰到 MySQL 的间隙锁一起研究。

条件查询和幻象现象(Phantom Phenomenon)

在不考虑 MVCC 的情况下考虑下面两个事务:

T1:

1
select count(*) from instructor where dept name = 'Physics'

T2:

1
insert into instructor values (11111,’Feynman’, ’Physics’, 94000);

T1 的查询和 T2 的写入是冲突的,如果事务执行序列是 T1 => T2,那么最终的调度就要求是 select 要发生在 insert 之前。如果一个调度的 insert 发生在前,那么这个调度不是一个冲突可串行化调度,这个调度的执行结果和 T1 => T2 的执行结果不一样。

Read more

数据库索引结构

聚簇索引和辅助索引

如果数据按照索引的顺序排列存储在磁盘上,称这个索引为聚簇索引:

Read more

数据库并发控制相关的一些问题和总结

最近在研究数据库事务和并发控制,主要的学习资料是《数据库系统概念 第六版》。本文记录了一些自己的理解和问题。如果同样在看这本书或者在研究类似问题的有兴趣可以看一下。这本书描述的东西比较理论,但是对数据库的各种问题的描述比较深入,相比网上的一些文章更加能接触到「真正的东西」,比较推荐。

一些待解决的问题

  1. 为什么需要设计共享锁和排他锁?还有意向锁。

  2. SELECT * FROM child WHERE id = 100;
    

    If id is not indexed or has a nonunique index, the statement does lock the preceding gap.

    为什么这种语句需要加间隙锁?没道理啊 …

    答:光 select 是不加锁的,select for update 或者加共享锁才会。光 select 会直接读 MVCC 的快照。

  3. 各种锁是如何被数据库系统使用的,如何用锁解决了数据库的一致性和隔离性要求
    答:锁锁住了数据,避免了并行执行事务之间的冲突。

锁的目的:是为了实现并发事务控制。各种锁:行锁、间隙锁、next-key 锁。

Read more

数据库隔离级别和各个级别下的缺点

2021-01-20 更新

Mysql RR 级别,使用 next-key lock(record lock + gap lock)解决了当前读的幻读问题,但是还是有一些场景能重现出幻读问题,就比如:

  1. create table ab(a int primary key, b int);
  2. Tx1:
    begin;
    select * from ab; // empty set
  3. Tx2:
    begin;
    insert into ab values(1,1);
    commit;
  4. Tx1:
    select * from ab; // empty set, expected phantom read missing.
    update ab set b = 2 where a = 1; // 1 row affected.
    select * from ab; // 1 row. phantom read here!!!!
    commit;

例子来自:https://stackoverflow.com/questions/5444915/how-to-produce-phantom-reads

2021-01-07 更新

对幻读加一个总结,RR 下的幻读其实是「快照读不存在,当前读存在,而且是针对的新增数据来说」,一会儿有,一会儿没有,像幻影一样。

2018 - 04 - 19 更新

今天突然感觉对 RC 下的不可重复读不太理解了,然后找了些网上的资料回顾下。比如 MySQL 四种事务隔离级的说明,发现大家在测不可重复读和可重复读的时候,都只直接用 select 去查的,也就是快照读。但是其实 RC 和 RR 下都是有 MVCC 的,自己又弄了几个例子测了测。本来理解的是无论 RC 还是 RR,只要在一个事务内的 select 都应该返回一样的结果。RC 下的不可重复读应该是对当前读来说的,RC 下的快照读本来也以为是能两次查询返回一致的。但是自己跑去测了下发现 RC 下两次读其实能读到其他事务提交的新数据,但是对数据的更新读取不到,还是只能读取到快照。

2018 - 03 - 02 更新

幻读:同一个事务的两次查询(delete insert update 触发唯一约束也算查询)第一次查没有,第二次查又有。幻体现在开始看没有,转头一看又有了,跟平时理解的幻觉有点相反。平时理解的幻觉是当时看有,之后看没有,怀疑当时出现了幻觉。

Read more