summaryrefslogtreecommitdiff
path: root/myisam
diff options
context:
space:
mode:
authorunknown <ingo@mysql.com>2006-06-28 18:55:30 +0200
committerunknown <ingo@mysql.com>2006-06-28 18:55:30 +0200
commit7aa26e264582964b6e4df64980edbee8cde8cbd7 (patch)
treeb472a6c7fd5a989ba1fcb599bc6b8443ab059848 /myisam
parent65fcdee56e6ffccee45fc4ab70e6d3050fa0e20d (diff)
downloadmariadb-git-7aa26e264582964b6e4df64980edbee8cde8cbd7.tar.gz
Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert"
It was possible that fetching a record by an exact key value (including the record pointer) could return a record with a different key value. This happened only if a concurrent insert added a record with the searched key value after the fetching statement locked the table for read. The search succeded on the key value, but the record was rejected as it was past the file length that was remembered at start of the fetching statement. With other words it was rejected as being a concurrently inserted record. The action to recover from this problem was to fetch the record that is pointed at by the next key of the index. This was repeated until a record below the file length was found. I do now avoid this loop if an exact match was searched. If this match is beyond the file length, it is now treated as "key not found". There cannot be another key with the same record pointer. myisam/mi_rkey.c: Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert" Added a check for exact key match before searching for the next key that was not concurrently inserted. If an exact key match finds a concurrently inserted row, this must be treated as "key not found". sql/sql_class.cc: Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert" Fixed some DBUG_ENTER strings.
Diffstat (limited to 'myisam')
-rw-r--r--myisam/mi_rkey.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c
index 70122288d6c..41c2e173b70 100644
--- a/myisam/mi_rkey.c
+++ b/myisam/mi_rkey.c
@@ -66,6 +66,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
if (fast_mi_readinfo(info))
goto err;
+
if (share->concurrent_insert)
rw_rdlock(&share->key_root_lock[inx]);
@@ -77,14 +78,24 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
if (!_mi_search(info,keyinfo, key_buff, use_key_length,
myisam_read_vec[search_flag], info->s->state.key_root[inx]))
{
- while (info->lastpos >= info->state->data_file_length)
+ /*
+ If we are searching for an exact key (including the data pointer)
+ and this was added by an concurrent insert,
+ then the result is "key not found".
+ */
+ if ((search_flag == HA_READ_KEY_EXACT) &&
+ (info->lastpos >= info->state->data_file_length))
+ {
+ my_errno= HA_ERR_KEY_NOT_FOUND;
+ info->lastpos= HA_OFFSET_ERROR;
+ }
+ else while (info->lastpos >= info->state->data_file_length)
{
/*
Skip rows that are inserted by other threads since we got a lock
Note that this can only happen if we are not searching after an
exact key, because the keys are sorted according to position
*/
-
if (_mi_search_next(info, keyinfo, info->lastkey,
info->lastkey_length,
myisam_readnext_vec[search_flag],
@@ -92,6 +103,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
break;
}
}
+
if (share->concurrent_insert)
rw_unlock(&share->key_root_lock[inx]);