设为首页 加入收藏

TOP

MySQL+InnoDB semi-consitent read原理及实现分析(二)
2017-02-21 08:15:48 】 浏览:522
Tags:MySQL InnoDB semi-consitent read 原理 实现 分析
AD_TRY_SEMI_CONSISTENT;


// 至此,InnoDB的fetch next针对semi-consistent read的处理完毕


上面提到的是semi-consistent read的功能实现,除此之外,MySQL针对semi-consistent read,还做了优化措施:对于update scan返回的不满足条件的记录,提前放锁。


MySQL Server层流程


sql_update.cc::mysql_update()


// 判断当前scan返回的记录,是否满足update的where条件


? ? // 若满足,则进行update操作


if (!(select && select->skip_record())



// 若不满足update的where条件,则选择将当前记录上的行锁提前释放


else


table->file->unlock_row();


InnoDB Engine层流程


ha_innobd.cc::unlock_row();


switch (prebuilt->row_read_type)


// 若系统未设置参数innodb_locks_unsafe_for_binlog,同时隔离级别大于


? ? // TRX_ISO_READ_COMMITTED,则不可提前释放不满足条件的行锁


? ? // 否则可以提前释放不满足条件的行锁


case ROW_READ_WITH_LOCKS:


if (!srv_locks_unsafe_for_binlog &&


prebuilt->trx->isolation_level > TRX_ISO_READ_COMMITTED)


break;


// 若当前系统已采用SEMI_CONSISTENT read,但是没有锁等待,加锁直接成功


? ? // 那么此时直接释放不满足条件的行锁


case ROW_READ_TRY_SEMI_CONSISTENT:


row_unlock_for_mysql();


// 若当前系统已采用SEMI_CONSISTENT read,并且有锁等待,构造了commit版本


? ? // 没有在commit版本上加锁,因此也无锁可放,直接返回即可


case ROW_READ_DID_SEMI_CONSISTENT:


prebuilt->row_read_type = ROW_READ_TRY_SEMI_CONSISTENT;


break;


set binlog_format=mixed;


set session transaction isolation level repeatable read;


create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;


insert into t1 values (1),(2),(3),(4),(5),(6),(7);


session 1: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?session 2:


set autocommit=0;


update t1 set a = a + 10;


set binlog_format=mixed;


set session transaction isolation level read committed;


update t1 set a = a + 100 where a > 10;


此时,session 2不需要等待session 1,虽然session 1的更新后项满足session 2的条件,但是由于session 2进行了semi-consistent read,读取到的记录的前项为(1-7),不满足session 2的更新where条件,因此session 2直接返回。


session 2直接返回,0 rows affected。


set binlog_format=mixed;


set session transaction isolation level repeatable read;


create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;


insert into t1 values (1),(2),(3),(4),(5),(6),(7);


session 1: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?session 2:


set autocommit=0;


update t1 set a = a + 10;


commit;


set binlog_format=mixed;


set session transaction isolation level repeatable read;


set autocommit = 0;


update t1 set a = a + 100 where a < 10;


select * from t1 lock in share mode;


session 1在session 2开始前已经提交,session 2可以进行semi-consistent read。并且读到的都是session 1的更新后项,完成加锁。但是由于更新后项均不满足session 2的where条件,session 2会释放所有行上的锁(由MySQL Server层判断并调用unlock_row方法释放行锁)。


此时,session 1再次执行select * from t1 lock in share mode语句,直接成功。因为session 2已经将所有的行锁提前释放。


朋友们可以试试将session 2的隔离级别改为repeatable read,那么此时session 1就会等待session 2提交。


首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇MySQL 中隔离级别 RC 与 RR 的区别 下一篇MySQL半一致性读导致语句级Binlog..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目