Skip to content
This repository has been archived by the owner on Jun 12, 2020. It is now read-only.

Patch for prelocking index and range scans

RIch Prohaska edited this page May 19, 2014 · 1 revision

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
Clone this wiki locally