失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > mysql mvcc 并发update_关于mysql的InnoDB多版本并发控制(MVCC)与事务隔离级别的疑问?...

mysql mvcc 并发update_关于mysql的InnoDB多版本并发控制(MVCC)与事务隔离级别的疑问?...

时间:2023-12-25 14:29:30

相关推荐

mysql mvcc 并发update_关于mysql的InnoDB多版本并发控制(MVCC)与事务隔离级别的疑问?...

1.会

2.取决于怎么定义phantom,以及有没有使用locking read。

MYSQL默认隔离级别按照SQL92的标准是REPEATABLE-READ,实际是SNAPSHOT。一些说法说SNAPSHOT可以避免phantom,也有一些说法说SNAPSHOT无法避免phantom。

其实这取决于怎么定义phantom,如果phantom专指【1】里面提到的anomaly,读到了不该读到的元组。 如果phantom也包括【2】里面提到的anomaly, 应该读到的元组没有读到。有些文章把为【2】里的anomaly都叫做write skew,不归类到phantom。

只需要记住,SNAPSHOT不会发生【1】提到的anomaly,但会发生【2】提到的anomaly。

例如,assignments表有四列(eid, pid, workdate, hours)。assignments表示的是给employee(eid)分配project(pid),并记录某个工作日(workdate)的工时(hours)。限制每个工作日工时不超过8小时。

assign表示分配工时的存储过程,假设eid为1的员工已有两个project, 工时分别为4,1。有两个并发的事务T1, T2, 同时执行assign。当T1,T2开始时,对于满足eid = 1 and workdate = '.3.1' 的元组,拿到的是相同的快照,它们都判定插入一条工时为4的元组不会使当日工时大于8。

如果把隔离级别改成SERIALIZABLE,就不会发生anomaly。因为在SERIALIZABLE隔离级别下会加谓词锁,并发控制算法变成了MV2PL。

create table assignments(

eid int ,

pid int,

workdate date,

hour int

);

insert into assignments values(1, 100, '.3.1', 4);

insert into assignments values(1, 101, '.3.1', 1);

delimiter //

create procedure assign(p_eid int, p_pid int, p_workdate date, p_hour int)

begin

declare v_hour int default 0;

select sum(hour) into v_hour from assignments where eid = p_eid and workdate = p_workdate;

if v_hour + p_hour <= 8 then

insert into assignments values(p_eid, p_pid, p_workdate, p_hour);

end if;

end//

delimiter ;

T1,T2执行前:

mysql> select * from assignments where eid = 1;

+------+------+------------+------+

| eid | pid | workdate | hour |

+------+------+------------+------+

| 1 | 100 | -03-01 | 4 |

| 1 | 101 | -03-01 | 1 |

+------+------+------------+------+

2 rows in set (0.00 sec)

事务T1:

set transaction_isolation='REPEATABLE-READ';

start transaction;

call assign(1, 102, '.3.1', 2);

commit;

事务T2:

set transaction_isolation='REPEATABLE-READ';

start transaction;

call assign(1, 103, '.3.1', 2);

commit;

T1,T2执行后:

mysql> select * from assignments where eid = 1;

+------+------+------------+------+

| eid | pid | workdate | hour |

+------+------+------------+------+

| 1 | 100 | -03-01 | 4 |

| 1 | 101 | -03-01 | 1 |

| 1 | 102 | -03-01 | 2 |

| 1 | 103 | -03-01 | 2 |

+------+------+------------+------+

4 rows in set (0.00 sec)

可以分析下这个例子里的异常是怎么产生的。T1,T2 并行的执行,事务开始,它们拿到的是相同的快照,都认为不会使当日工时大于8,于是都插入了一条记录。两个事务提交时,当日工时大于8了。

下面是更形式化的分析。T1用谓词P1读,T2插入了一条满足谓词P1的记录,所以存在一个T1到T2的rw(read write)依赖(T1应先于T2发生)。同时,也存在同样的T2到T1依赖。这样就有一个循环依赖,所以这个调度就不是串行化的,发生了异常。

判断并发执行的SQL会不会有异常,需要判断是否有循环的依赖。一个有用的技术是,找是否可能存在两个连续的rw依赖。因为在snapshot(MySQL的RR)隔离级别下,两个连续的rw依赖产生是发生不可串行化异常的必要不充分条件。具体细节和方法可以去参考论文【2】,论文最后用这个方法分析TPC-C为什么在snapshot下不会有异常。

还有,MySQL有一个比较特殊的情形,就是它允许覆盖更新这种行为(不遵守first commit win rule),这让它产生了另一种异常。

如下面的例子,有两个事务,在RR隔离级别下, select是没有幻读的,但select for update却会产生幻读。因为select是读,通过时间戳读快照,事务2读不到事务1的写入。而select for update被认为是写,是可以更新已提交数据的,所以读到的是最新版本,事务2可以读到事务1的写入。

事务1 事务2

mysql> start transaction; mysql> start transaction;

Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec)

mysql> select * from t;

Empty set (0.00 sec)

mysql> insert into t values(1);

Query OK, 1 row affected (0.00 sec)

mysql> commit;

Query OK, 0 rows affected (0.01 sec)

// no phantom

mysql> select * from t;

Empty set (0.00 sec)

// phantom

mysql> select * from t for update;

+------+

| c |

+------+

| 1 |

+------+

1 row in set (0.00 sec)

// update committed row

mysql> update t set c=2;

Query OK, 0 rows affected (0.00 sec)

Rows matched: 1 Changed: 0 Warnings: 0

mysql> commit;

Query OK, 0 rows affected (0.01 sec)

参考:

【1】ESWARAN, K., GRAY, J., LORIE, R., AND TRAIGER, I. 1976. The notions of consistency and predicate locks in a database system. Commun. ACM 19, 11 (Nov.), 624–633

【2】Alan Fekete, Dimitrios Liarokapis, Elizabeth J. O'Neil, Patrick E. O'Neil, Dennis E. Shasha: Making snapshot isolation serializable. ACM Trans. Database Syst. 30(2): 492-528 ()

如果觉得《mysql mvcc 并发update_关于mysql的InnoDB多版本并发控制(MVCC)与事务隔离级别的疑问?...》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。