summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-11-19 13:16:25 +0100
committerSergei Golubchik <sergii@pisem.net>2013-11-19 13:16:25 +0100
commitfa3f8a18b247d5d7d86d60d016681cc188522f80 (patch)
tree180232f5e13c81e22ae9374b41be168ed9578932 /storage
parentefab095c7f8f044525ce7d2313fad5f86032baab (diff)
parent543b6e02246db25d8a61574fc709b28e7720d1a0 (diff)
downloadmariadb-git-fa3f8a18b247d5d7d86d60d016681cc188522f80.tar.gz
mysql-5.5.34 merge
(some patches reverted, test case added)
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/btr/btr0cur.c18
-rw-r--r--storage/innobase/buf/buf0buf.c46
-rw-r--r--storage/innobase/handler/ha_innodb.cc35
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.c3
-rw-r--r--storage/innobase/row/row0mysql.c20
-rw-r--r--storage/innobase/row/row0sel.c3
-rw-r--r--storage/innobase/row/row0uins.c15
-rw-r--r--storage/innobase/row/row0umod.c46
-rw-r--r--storage/myisam/mi_check.c12
9 files changed, 137 insertions, 61 deletions
diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c
index b48fb705cd8..81a482e2854 100644
--- a/storage/innobase/btr/btr0cur.c
+++ b/storage/innobase/btr/btr0cur.c
@@ -4596,6 +4596,10 @@ next_zip_page:
}
}
}
+
+ DBUG_EXECUTE_IF("btr_store_big_rec_extern",
+ error = DB_OUT_OF_FILE_SPACE;
+ goto func_exit;);
}
func_exit:
@@ -4628,9 +4632,11 @@ func_exit:
field_ref = btr_rec_get_field_ref(rec, offsets, i);
- /* The pointer must not be zero. */
+ /* The pointer must not be zero if the operation
+ succeeded. */
ut_a(0 != memcmp(field_ref, field_ref_zero,
- BTR_EXTERN_FIELD_REF_SIZE));
+ BTR_EXTERN_FIELD_REF_SIZE)
+ || error != DB_SUCCESS);
/* The column must not be disowned by this record. */
ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
}
@@ -4726,10 +4732,10 @@ btr_free_externally_stored_field(
if (UNIV_UNLIKELY(!memcmp(field_ref, field_ref_zero,
BTR_EXTERN_FIELD_REF_SIZE))) {
- /* In the rollback of uncommitted transactions, we may
- encounter a clustered index record whose BLOBs have
- not been written. There is nothing to free then. */
- ut_a(rb_ctx == RB_RECOVERY || rb_ctx == RB_RECOVERY_PURGE_REC);
+ /* In the rollback, we may encounter a clustered index
+ record with some unwritten off-page columns. There is
+ nothing to free then. */
+ ut_a(rb_ctx != RB_NONE);
return;
}
diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
index ab4f077bdfd..13c68169f37 100644
--- a/storage/innobase/buf/buf0buf.c
+++ b/storage/innobase/buf/buf0buf.c
@@ -2290,7 +2290,6 @@ loop:
buf_pool, space, offset, fold);
}
-loop2:
if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
block = NULL;
}
@@ -2407,6 +2406,11 @@ wait_until_unfixed:
goto loop;
}
+ /* Buffer-fix the block so that it cannot be evicted
+ or relocated while we are attempting to allocate an
+ uncompressed page. */
+ bpage->buf_fix_count++;
+
/* Allocate an uncompressed page. */
buf_pool_mutex_exit(buf_pool);
mutex_exit(&buf_pool->zip_mutex);
@@ -2416,34 +2420,20 @@ wait_until_unfixed:
buf_pool_mutex_enter(buf_pool);
mutex_enter(&block->mutex);
+ mutex_enter(&buf_pool->zip_mutex);
+ /* Buffer-fixing prevents the page_hash from changing. */
+ ut_ad(bpage == buf_page_hash_get_low(buf_pool,
+ space, offset, fold));
- {
- buf_page_t* hash_bpage;
-
- hash_bpage = buf_page_hash_get_low(
- buf_pool, space, offset, fold);
-
- if (UNIV_UNLIKELY(bpage != hash_bpage)) {
- /* The buf_pool->page_hash was modified
- while buf_pool->mutex was released.
- Free the block that was allocated. */
-
- buf_LRU_block_free_non_file_page(block);
- mutex_exit(&block->mutex);
-
- block = (buf_block_t*) hash_bpage;
- goto loop2;
- }
- }
-
- if (UNIV_UNLIKELY
- (bpage->buf_fix_count
- || buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
+ if (--bpage->buf_fix_count
+ || buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
- /* The block was buffer-fixed or I/O-fixed
- while buf_pool->mutex was not held by this thread.
- Free the block that was allocated and try again.
- This should be extremely unlikely. */
+ mutex_exit(&buf_pool->zip_mutex);
+ /* The block was buffer-fixed or I/O-fixed while
+ buf_pool->mutex was not held by this thread.
+ Free the block that was allocated and retry.
+ This should be extremely unlikely, for example,
+ if buf_page_get_zip() was invoked. */
buf_LRU_block_free_non_file_page(block);
mutex_exit(&block->mutex);
@@ -2454,8 +2444,6 @@ wait_until_unfixed:
/* Move the compressed page from bpage to block,
and uncompress it. */
- mutex_enter(&buf_pool->zip_mutex);
-
buf_relocate(bpage, &block->page);
buf_block_init_low(block);
block->lock_hash_val = lock_rec_hash(space, offset);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 7a758c66b31..9c16cf73952 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -90,6 +90,9 @@ extern "C" {
#include "ha_prototypes.h"
#include "ut0mem.h"
#include "ibuf0ibuf.h"
+
+enum_tx_isolation thd_get_trx_isolation(const THD* thd);
+
}
#include "ha_innodb.h"
@@ -395,6 +398,15 @@ innobase_alter_table_flags(
/*=======================*/
uint flags);
+/******************************************************************//**
+Maps a MySQL trx isolation level code to the InnoDB isolation level code
+@return InnoDB isolation level */
+static inline
+ulint
+innobase_map_isolation_level(
+/*=========================*/
+ enum_tx_isolation iso); /*!< in: MySQL isolation level code */
+
static const char innobase_hton_name[]= "InnoDB";
/*************************************************************//**
@@ -1196,7 +1208,8 @@ innobase_convert_from_id(
}
/**********************************************************************
-Converts an identifier from my_charset_filename to UTF-8 charset. */
+Converts an identifier from my_charset_filename to UTF-8 charset.
+@return result string length, as returned by strconvert() */
extern "C"
uint
innobase_convert_to_system_charset(
@@ -2745,9 +2758,22 @@ innobase_start_trx_and_assign_read_view(
trx_start_if_not_started(trx);
- /* Assign a read view if the transaction does not have it yet */
+ /* Assign a read view if the transaction does not have it yet.
+ Do this only if transaction is using REPEATABLE READ isolation
+ level. */
+ trx->isolation_level = innobase_map_isolation_level(
+ thd_get_trx_isolation(thd));
- trx_assign_read_view(trx);
+ if (trx->isolation_level == TRX_ISO_REPEATABLE_READ) {
+ trx_assign_read_view(trx);
+ } else {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ HA_ERR_UNSUPPORTED,
+ "InnoDB: WITH CONSISTENT SNAPSHOT "
+ "was ignored because this phrase "
+ "can only be used with "
+ "REPEATABLE READ isolation level.");
+ }
/* Set the MySQL flag to mark that there is an active transaction */
@@ -12142,7 +12168,8 @@ test_innobase_convert_name()
#endif /* UNIV_COMPILE_TEST_FUNCS */
/**********************************************************************
-Converts an identifier from my_charset_filename to UTF-8 charset. */
+Converts an identifier from my_charset_filename to UTF-8 charset.
+@return result string length, as returned by strconvert() */
extern "C"
uint
innobase_convert_to_filename_charset(
diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c
index 0351951f3d2..306cdefc304 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.c
+++ b/storage/innobase/ibuf/ibuf0ibuf.c
@@ -4373,7 +4373,6 @@ ibuf_delete_rec(
BTR_MODIFY_TREE, pcur, mtr)) {
mutex_exit(&ibuf_mutex);
- ut_ad(!ibuf_inside(mtr));
ut_ad(mtr->state == MTR_COMMITTED);
goto func_exit;
}
@@ -4394,7 +4393,6 @@ ibuf_delete_rec(
ibuf_btr_pcur_commit_specify_mtr(pcur, mtr);
func_exit:
- ut_ad(!ibuf_inside(mtr));
ut_ad(mtr->state == MTR_COMMITTED);
btr_pcur_close(pcur);
@@ -4731,7 +4729,6 @@ loop:
BTR_MODIFY_LEAF,
&pcur, &mtr)) {
- ut_ad(!ibuf_inside(&mtr));
ut_ad(mtr.state == MTR_COMMITTED);
mops[op]++;
ibuf_dummy_index_free(dummy_index);
diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c
index 5c9eadeb71a..8555054b86f 100644
--- a/storage/innobase/row/row0mysql.c
+++ b/storage/innobase/row/row0mysql.c
@@ -3958,12 +3958,28 @@ row_rename_table_for_mysql(
} else if (!new_is_tmp) {
/* Rename all constraints. */
char new_table_name[MAX_TABLE_NAME_LEN] = "";
+ char old_table_utf8[MAX_TABLE_NAME_LEN] = "";
uint errors = 0;
+ strncpy(old_table_utf8, old_name, MAX_TABLE_NAME_LEN);
+ innobase_convert_to_system_charset(
+ strchr(old_table_utf8, '/') + 1,
+ strchr(old_name, '/') +1,
+ MAX_TABLE_NAME_LEN, &errors);
+
+ if (errors) {
+ /* Table name could not be converted from charset
+ my_charset_filename to UTF-8. This means that the
+ table name is already in UTF-8 (#mysql#50). */
+ strncpy(old_table_utf8, old_name, MAX_TABLE_NAME_LEN);
+ }
+
info = pars_info_create();
pars_info_add_str_literal(info, "new_table_name", new_name);
pars_info_add_str_literal(info, "old_table_name", old_name);
+ pars_info_add_str_literal(info, "old_table_name_utf8",
+ old_table_utf8);
strncpy(new_table_name, new_name, MAX_TABLE_NAME_LEN);
innobase_convert_to_system_charset(
@@ -4000,6 +4016,8 @@ row_rename_table_for_mysql(
"new_db_name := SUBSTR(:new_table_name, 0,\n"
" new_db_name_len);\n"
"old_t_name_len := LENGTH(:old_table_name);\n"
+ "gen_constr_prefix := CONCAT(:old_table_name_utf8,\n"
+ " '_ibfk_');\n"
"WHILE found = 1 LOOP\n"
" SELECT ID INTO foreign_id\n"
" FROM SYS_FOREIGN\n"
@@ -4016,7 +4034,7 @@ row_rename_table_for_mysql(
" id_len := LENGTH(foreign_id);\n"
" IF (INSTR(foreign_id, '/') > 0) THEN\n"
" IF (INSTR(foreign_id,\n"
- " '_ibfk_') > 0)\n"
+ " gen_constr_prefix) > 0)\n"
" THEN\n"
" offset := INSTR(foreign_id, '_ibfk_') - 1;\n"
" new_foreign_id :=\n"
diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c
index e4c7e37307b..518eba975ab 100644
--- a/storage/innobase/row/row0sel.c
+++ b/storage/innobase/row/row0sel.c
@@ -217,7 +217,8 @@ row_sel_sec_rec_is_for_clust_rec(
len = clust_len;
- if (ifield->prefix_len > 0 && len != UNIV_SQL_NULL) {
+ if (ifield->prefix_len > 0 && len != UNIV_SQL_NULL
+ && sec_len != UNIV_SQL_NULL) {
if (rec_offs_nth_extern(clust_offs, clust_pos)) {
len -= BTR_EXTERN_FIELD_REF_SIZE;
diff --git a/storage/innobase/row/row0uins.c b/storage/innobase/row/row0uins.c
index 396cc6b3390..57c8c512698 100644
--- a/storage/innobase/row/row0uins.c
+++ b/storage/innobase/row/row0uins.c
@@ -340,13 +340,14 @@ row_undo_ins(
/* The database must have crashed after
inserting a clustered index record but before
writing all the externally stored columns of
- that record. Because secondary index entries
- are inserted after the clustered index record,
- we may assume that the secondary index record
- does not exist. However, this situation may
- only occur during the rollback of incomplete
- transactions. */
- ut_a(trx_is_recv(node->trx));
+ that record, or a statement is being rolled
+ back because an error occurred while storing
+ off-page columns.
+
+ Because secondary index entries are inserted
+ after the clustered index record, we may
+ assume that the secondary index record does
+ not exist. */
} else {
log_free_check();
err = row_undo_ins_remove_sec(node->index, entry);
diff --git a/storage/innobase/row/row0umod.c b/storage/innobase/row/row0umod.c
index fae67c95c43..69831fee8ac 100644
--- a/storage/innobase/row/row0umod.c
+++ b/storage/innobase/row/row0umod.c
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -128,11 +128,10 @@ row_undo_mod_clust_low(
}
/***********************************************************//**
-Removes a clustered index record after undo if possible.
+Purges a clustered index record after undo if possible.
This is attempted when the record was inserted by updating a
delete-marked record and there no longer exist transactions
-that would see the delete-marked record. In other words, we
-roll back the insert by purging the record.
+that would see the delete-marked record.
@return DB_SUCCESS, DB_FAIL, or error code: we may run out of file space */
static
ulint
@@ -140,11 +139,12 @@ row_undo_mod_remove_clust_low(
/*==========================*/
undo_node_t* node, /*!< in: row undo node */
que_thr_t* thr, /*!< in: query thread */
- mtr_t* mtr, /*!< in: mtr */
+ mtr_t* mtr, /*!< in/out: mini-transaction */
ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
{
btr_cur_t* btr_cur;
ulint err;
+ ulint trx_id_offset;
ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC);
@@ -159,6 +159,42 @@ row_undo_mod_remove_clust_low(
btr_cur = btr_pcur_get_btr_cur(&node->pcur);
+ trx_id_offset = btr_cur_get_index(btr_cur)->trx_id_offset;
+
+ if (!trx_id_offset) {
+ mem_heap_t* heap = NULL;
+ ulint trx_id_col;
+ ulint* offsets;
+ ulint len;
+
+ trx_id_col = dict_index_get_sys_col_pos(
+ btr_cur_get_index(btr_cur), DATA_TRX_ID);
+ ut_ad(trx_id_col > 0);
+ ut_ad(trx_id_col != ULINT_UNDEFINED);
+
+ offsets = rec_get_offsets(
+ btr_cur_get_rec(btr_cur), btr_cur_get_index(btr_cur),
+ NULL, trx_id_col + 1, &heap);
+
+ trx_id_offset = rec_get_nth_field_offs(
+ offsets, trx_id_col, &len);
+ ut_ad(len == DATA_TRX_ID_LEN);
+ mem_heap_free(heap);
+ }
+
+ if (trx_read_trx_id(btr_cur_get_rec(btr_cur) + trx_id_offset)
+ != node->new_trx_id) {
+ /* The record must have been purged and then replaced
+ with a different one. */
+ return(DB_SUCCESS);
+ }
+
+ /* We are about to remove an old, delete-marked version of the
+ record that may have been delete-marked by a different transaction
+ than the rolling-back one. */
+ ut_ad(rec_get_deleted_flag(btr_cur_get_rec(btr_cur),
+ dict_table_is_comp(node->table)));
+
if (mode == BTR_MODIFY_LEAF) {
err = btr_cur_optimistic_delete(btr_cur, mtr)
? DB_SUCCESS
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index 7e97a751376..98a87a4e915 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -2629,6 +2629,7 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info,
ulonglong UNINIT_VAR(key_map);
pthread_attr_t thr_attr;
ulong max_pack_reclength;
+ int error;
DBUG_ENTER("mi_repair_parallel");
start_records=info->state->records;
@@ -2926,12 +2927,13 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info,
#else
param->sort_buffer_length*sort_param[i].key_length/total_key_length;
#endif
- if (mysql_thread_create(mi_key_thread_find_all_keys,
- &sort_param[i].thr, &thr_attr,
- thr_find_all_keys,
- (void *) (sort_param+i)))
+ if ((error= mysql_thread_create(mi_key_thread_find_all_keys,
+ &sort_param[i].thr, &thr_attr,
+ thr_find_all_keys,
+ (void *) (sort_param+i))))
{
- mi_check_print_error(param,"Cannot start a repair thread");
+ mi_check_print_error(param,"Cannot start a repair thread (errno= %d)",
+ error);
/* Cleanup: Detach from the share. Avoid others to be blocked. */
if (io_share.total_threads)
remove_io_thread(&sort_param[i].read_cache);