Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug#84958 - InnoDB's MVCC has O(N^2) behaviors (#975)
Summary: (Also fixes PS-4712 - Assertion after bug#84958 fix on FB tree) Problem: If there're multiple row versions in InnoDB, reading one row from PK may have O(N) complexity and reading from secondary keys may have O(N^2) complexity. Fix: The problem occurs when there are many pending versions of the same row, meaning that the primary key is the same, but a secondary key is different. The slowdown occurs when the secondary index is traversed. This patch creates a helper class for the function row_sel_get_clust_rec_for_mysql() which can remember and re-use cached_clust_rec & cached_old_vers so that rec_get_offsets() does not need to be called over and over for the clustered record. PS-4712 : Assertion after bug#84958 fix on FB tree Problem: The function row_sel_build_prev_vers_for_mysql() goes through the old versions of the clustered index record and identifies the one which can be viewed by the current transaction (MVCC). The result is then cached in an object of Row_sel_get_clust_rec_for_mysql. The two things that are cached by the helper class Row_sel_get_clust_rec_for_mysql are cached_clust_rec and cached_old_vers. If the latest record is cached_clust_rec, its old version for the given transaction that is viewable is cached_old_vers. The important point here is that the record offsets for these two records are not cached. The record offsets for cached_clust_rec and the cached_old_vers need not be the same. This is confirmed by looking at row_sel_build_prev_vers_for_mysql(). The 6th argument which contains the record offsets is an input/output argument. The input is the offsets of the latest version of clust_rec, and the output is the record offsets of the older version. So the record offsets of different versions of clust_rec can change. Solution: Re-calculate the record offsets for the cached old_vers. Pull Request resolved: #975 Reviewed By: lth Differential Revision: D14282030 Pulled By: lth fbshipit-source-id: 7dc2d23
- Loading branch information
1 parent
7703200
commit f7d9a8d
Showing
3 changed files
with
239 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
create procedure insert_n(n int) | ||
begin | ||
declare i int default 0; | ||
while i < n do | ||
insert into t1 values (1, 2, 3) on duplicate key update c= c + 1; | ||
set i = i + 1; | ||
end while; | ||
end~~ | ||
create function bprrs() | ||
returns int | ||
begin | ||
declare ret int; | ||
select variable_value | ||
from information_schema.global_status | ||
where | ||
variable_name = 'innodb_buffer_pool_read_requests' | ||
into ret; | ||
return ret; | ||
end~~ | ||
create table t1 (a int, b int, c int, primary key(a,b), key (b,c)) engine=InnoDB; | ||
begin; | ||
select * from t1; | ||
a b c | ||
call insert_n(100); | ||
set @rr1= bprrs(); | ||
select * from t1 force index (b); | ||
a b c | ||
set @rr2= bprrs(); | ||
select @rr2 - @rr1 < 1000; | ||
@rr2 - @rr1 < 1000 | ||
1 | ||
drop table t1; | ||
create table t1 (a int, b int, c int, primary key(a,b), key (b,c)) engine=innodb; | ||
insert into t1 values (1,2,3) on duplicate key update c=c+1; | ||
begin; | ||
select * from t1; | ||
a b c | ||
1 2 3 | ||
insert into t1 values (1,2,3) on duplicate key update c=null; | ||
insert into t1 values (1,2,3) on duplicate key update c=null; | ||
insert into t1 values (1,2,3) on duplicate key update c=null; | ||
select * from t1 force index (primary); | ||
a b c | ||
1 2 3 | ||
select * from t1 force index (b); | ||
a b c | ||
1 2 3 | ||
commit; | ||
drop table t1; | ||
drop procedure insert_n; | ||
drop function bprrs; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# | ||
# Bug #84958 InnoDB's MVCC has O(N^2) behaviors | ||
# https://bugs.mysql.com/bug.php?id=84958 | ||
# | ||
|
||
--source include/have_innodb.inc | ||
--source include/count_sessions.inc | ||
|
||
delimiter ~~; | ||
create procedure insert_n(n int) | ||
begin | ||
declare i int default 0; | ||
while i < n do | ||
insert into t1 values (1, 2, 3) on duplicate key update c= c + 1; | ||
set i = i + 1; | ||
end while; | ||
end~~ | ||
|
||
create function bprrs() | ||
returns int | ||
begin | ||
declare ret int; | ||
select variable_value | ||
from information_schema.global_status | ||
where | ||
variable_name = 'innodb_buffer_pool_read_requests' | ||
into ret; | ||
return ret; | ||
end~~ | ||
delimiter ;~~ | ||
|
||
create table t1 (a int, b int, c int, primary key(a,b), key (b,c)) engine=InnoDB; | ||
|
||
connect (con2, localhost, root,,); | ||
|
||
begin; | ||
select * from t1; | ||
|
||
connection con2; | ||
call insert_n(100); | ||
|
||
connection default; | ||
set @rr1= bprrs(); | ||
|
||
select * from t1 force index (b); | ||
set @rr2= bprrs(); | ||
select @rr2 - @rr1 < 1000; | ||
|
||
disconnect con2; | ||
|
||
connection default; | ||
drop table t1; | ||
|
||
# This testcase verifies that we return correct offsets when returning old_version | ||
# of a cluster index record. | ||
|
||
create table t1 (a int, b int, c int, primary key(a,b), key (b,c)) engine=innodb; | ||
|
||
insert into t1 values (1,2,3) on duplicate key update c=c+1; | ||
|
||
begin; | ||
select * from t1; | ||
|
||
connect (con2, localhost, root,,); | ||
--connection con2 | ||
|
||
--let $i=3 | ||
while ($i) | ||
{ | ||
insert into t1 values (1,2,3) on duplicate key update c=null; | ||
--dec $i | ||
} | ||
|
||
--connection default | ||
select * from t1 force index (primary); | ||
select * from t1 force index (b); | ||
|
||
commit; | ||
|
||
disconnect con2; | ||
|
||
connection default; | ||
drop table t1; | ||
drop procedure insert_n; | ||
drop function bprrs; | ||
--source include/wait_until_count_sessions.inc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters