3898 Vasil Dimov 2012-05-25
In dict_stats_analyze_index_for_n_prefix() we could try to dive below
the supremum in an edge case where the tree has changed in such a way
that dive_below_idx is the index of the supremum record.
Treat this as if the tree has shrunk a bit more - just quite the scan.
modified:
storage/innobase/dict/dict0stats.cc
3897 Vasil Dimov 2012-05-25
Use a dedicated trx in dict_stats_drop_index() instead of prebuilt->trx
because prebuilt->trx is not committed and the following scenario causes
a lock wait timeout:
SET GLOBAL innodb_stats_persistent=1;
CREATE TABLE t1 (i INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (i INT, FOREIGN KEY (i) REFERENCES t1 (i)) ENGINE=InnoDB;
CREATE INDEX ind2 ON t2(i);
The CREATE INDEX command drops the implicitly added index "i" on t2 and
tries to add a new index before committing the trx. So we end up with
DELETE FROM mysql.innodb_index_stats dangling uncommitted and later
INSERT/UPDATE in another trx by dict_stats_save() which causes lock wait
timeout.
With this change all code that deals with mysql.innodb_table_stats or
mysql.innodb_index_stats creates a dedicated trx locally and commits it.
modified:
storage/innobase/dict/dict0stats.cc
storage/innobase/handler/handler0alter.cc
storage/innobase/include/dict0stats.h
3896 Mayank Prasad 2012-05-25 [merge]
NUll merge: 5.5->trunk
=== modified file 'storage/innobase/dict/dict0stats.cc'
--- a/storage/innobase/dict/dict0stats.cc revid:mayank.prasad@stripped
+++ b/storage/innobase/dict/dict0stats.cc revid:vasil.dimov@stripped
@@ -1249,6 +1249,14 @@ dict_stats_analyze_index_for_n_prefix(
break;
}
+ /* it could be that the tree has changed in such a way that
+ the record under dive_below_idx is the supremum record, in
+ this case rec_idx == dive_below_idx and pcur is positioned
+ on the supremum, we do not want to dive below it */
+ if (!btr_pcur_is_on_user_rec(&pcur)) {
+ break;
+ }
+
ut_a(rec_idx == dive_below_idx);
ib_uint64_t n_diff_on_leaf_page;
@@ -2706,10 +2714,7 @@ transient:
/*********************************************************************//**
Removes the information for a particular index's stats from the persistent
storage if it exists and if there is data stored for this index.
-The transaction is not committed, it must not be committed in this
-function because this is the user trx that is running DROP INDEX.
-The transaction will be committed at the very end when dropping an
-index.
+This function creates its own trx and commits it.
A note from Marko why we cannot edit user and sys_* tables in one trx:
marko: The problem is that ibuf merges should be disabled while we are
rolling back dict transactions.
@@ -2724,7 +2729,6 @@ dict_stats_drop_index(
/*==================*/
const char* tname, /*!< in: table name, e.g. 'db/table' */
const char* iname, /*!< in: index name */
- trx_t* trx, /*!< in/out: user transaction */
char* errstr, /*!< out: error message if != DB_SUCCESS
is returned */
ulint errstr_sz)/*!< in: size of the errstr buffer */
@@ -2734,7 +2738,6 @@ dict_stats_drop_index(
pars_info_t* pinfo;
dberr_t ret;
dict_stats_t* dict_stats;
- THD* mysql_thd;
ut_ad(!mutex_own(&dict_sys->mutex));
@@ -2769,11 +2772,10 @@ dict_stats_drop_index(
pars_info_add_str_literal(pinfo, "index_name", iname);
- /* Force lock wait timeout to be instantaneous because the incoming
- transaction was created via MySQL. */
+ trx_t* trx;
- mysql_thd = trx->mysql_thd;
- trx->mysql_thd = NULL;
+ trx = trx_allocate_for_background();
+ trx_start_if_not_started(trx);
mutex_enter(&dict_sys->mutex);
@@ -2791,11 +2793,13 @@ dict_stats_drop_index(
mutex_exit(&dict_sys->mutex);
- trx->mysql_thd = mysql_thd;
-
- /* do not to commit here, see the function's comment */
-
- if (ret != DB_SUCCESS) {
+ if (ret == DB_SUCCESS) {
+ trx_commit_for_mysql(trx);
+ } else {
+ trx->op_info = "rollback of internal trx on stats tables";
+ trx_rollback_to_savepoint(trx, NULL);
+ trx->op_info = "";
+ ut_a(trx->error_state == DB_SUCCESS);
ut_snprintf(errstr, errstr_sz,
"Unable to delete statistics for index %s "
@@ -2817,9 +2821,8 @@ dict_stats_drop_index(
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: %s\n", errstr);
-
- trx->error_state = DB_SUCCESS;
}
+ trx_free_for_background(trx);
dict_stats_close(dict_stats);
=== modified file 'storage/innobase/handler/handler0alter.cc'
--- a/storage/innobase/handler/handler0alter.cc revid:mayank.prasad@stripped
+++ b/storage/innobase/handler/handler0alter.cc revid:vasil.dimov@stripped
@@ -3145,7 +3145,6 @@ trx_commit:
ret = dict_stats_drop_index(
prebuilt->table->name, key->name,
- prebuilt->trx,
errstr, sizeof(errstr));
if (ret != DB_SUCCESS) {
=== modified file 'storage/innobase/include/dict0stats.h'
--- a/storage/innobase/include/dict0stats.h revid:mayank.prasad@stripped
+++ b/storage/innobase/include/dict0stats.h revid:vasil.dimov@stripped
@@ -120,10 +120,7 @@ dict_stats_update(
/*********************************************************************//**
Removes the information for a particular index's stats from the persistent
storage if it exists and if there is data stored for this index.
-The transaction is not committed, it must not be committed in this
-function because this is the user trx that is running DROP INDEX.
-The transaction will be committed at the very end when dropping an
-index.
+This function creates its own trx and commits it.
@return DB_SUCCESS or error code */
UNIV_INTERN
dberr_t
@@ -131,7 +128,6 @@ dict_stats_drop_index(
/*==================*/
const char* tname, /*!< in: table name */
const char* iname, /*!< in: index name */
- trx_t* trx, /*!< in/out: user transaction */
char* errstr, /*!< out: error message if != DB_SUCCESS
is returned */
ulint errstr_sz);/*!< in: size of the errstr buffer */
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (vasil.dimov:3896 to 3898) | vasil.dimov | 25 May |