-
Notifications
You must be signed in to change notification settings - Fork 131
Patch for prelocking index and range scans
The prepare index scan patch notifies the storage engine that a full index scan is imminent. The prepare range scan patch notifies the storage engine that a range scan is imminent. This gives TokuDB the opportunity to do prelocking which speeds up the scans. If these patches are omitted, then TokuDB must lock each row as it is scanned. This can significantly increase the locking overhead of the queries.
The prepare index scan patch prelocks an entire index when a full index scan (either forward or backward) will occur. The 'prepare_index_scan' handler method is called from 'join_read_first' and 'join_read_last' since these handler methods start the scan. Both of these methods call the handler 'ha_index_first' and 'ha_index_last' methods, but we don't want to push the prelocking into these handler methods since these handler methods are called in many other places during query execution that may not do a full index scan.
The 'prepare_index_scan' handler method is called from 'rr_read_first' and 'rr_read_last'. Deletes and updates use this execution mode. Unfortunately, double locking occurs since the index is prelocked but each updated row gets locked.
The prepare range scan patch prelocks a range of keys and it called from 'QUICK_SELECT_DESC::get_next'.
For the following queries, we will see that use cases for prepare_index_scan and for prepare_range_scan.
create table t (id int primary key);
set session transaction isolation level repeatable read;
select * from t;
explain: ALL
execution: rnd_init, rnd_next*, rnd_end
locking: none
for update: tokudb::rnd_init -> prelock write -inf +inf
select * from t order by id;
explain: index PRIMARY
execution: index_init, index_first, index_next*, index_end
locking: none
for update: join_read_first -> prepare_index_scan -> prelock write -inf +inf
select * from t order by id desc;
explain: index PRIMARY
execution: index_init, index_last, index_prev*, index_end
locking: none
for update: join_read_last -> prepare_index_scan ->prelock write -inf +inf
select * from t where id > 2;
explain: range PRIMARY using where
execution: index_init, index_read, index_next*, index_end
locking: none
for update: multi_range_read_next -> read_range_first -> prelock write 2 +inf
select * from t where id > 2 order by id;
explain: range PRIMARY using where
execution: index_init, index_read, index_next*, index_end
locking: none
for update: multi_range_read_next -> read_range_first -> prelock write 2 +inf
select * from t where id > 2 order by id desc;
explain: range PRIMARY using where
execution: index_init, index_last, index_prev*, index_end
locking: none
for update: QUICK_SELECT_DESC::get_next -> prepare_range_scan -> prelock 2 +inf
select * from t where id < 2;
explain: range PRIMARY using where
execution: index_init, index_first, index_next*, index_end
locking: none
for update: QUICK_RANGE_SELECT::get_next -> multi_range_read_next -> read_range_first -> prelock -inf 2
select * from t where id < 2 order by id;
explain: range PRIMARY using where
execution: index_init, index_first, index_next*, index_end
locking: none
for update: QUICK_RANGE_SELECT::get_next -> multi_range_read_next -> read_range_first -> prelock -inf 2
select * from t where id < 2 order by id desc;
explain: range PRIMARY using where
execution: index_init, index_read, index_prev*, index_end
locking: none
for update: QUICK_SELECT_DESC::get_next -> prepare_range_scan -> prelock 2 +inf
update t set y=y+1 order by id limit 10;
explain: index PRIMARY using temporary
execution: rnd_init, rnd_pos, update, rnd_end
locking: rr_index_first -> prepare_index_scan, rnd_pos -> getf_set ..-> acquire point lock
problem: prelocking ignored
update t set y=y+1 order by id desc limit 10;
explain: index PRIMARY using temporary
execution: irnd_init, rnd_pos, update, rnd_end
locking: rr_index_last -> prepare_index_scan, index_last -> getf_last ..-> acquire point lock, rr_index_desc -> index_prev -> getf_prev ..-> acquire point lock
problem: no prelocking