Commit 57d6b444 authored by Andrei Elkin's avatar Andrei Elkin

merging from 5.1-bt rep to local branch

parents 41eda14f 3fcb25d8
...@@ -430,4 +430,24 @@ SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL; ...@@ -430,4 +430,24 @@ SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL;
b COUNT(DISTINCT a) b COUNT(DISTINCT a)
NULL 1 NULL 1
DROP TABLE t1; DROP TABLE t1;
#
# Bug#50995 Having clause on subquery result produces incorrect results.
#
CREATE TABLE t1
(
id1 INT,
id2 INT NOT NULL,
INDEX id1(id2)
);
INSERT INTO t1 SET id1=1, id2=1;
INSERT INTO t1 SET id1=2, id2=1;
INSERT INTO t1 SET id1=3, id2=1;
SELECT t1.id1,
(SELECT 0 FROM DUAL
WHERE t1.id1=t1.id1) AS amount FROM t1
WHERE t1.id2 = 1
HAVING amount > 0
ORDER BY t1.id1;
id1 amount
DROP TABLE t1;
End of 5.0 tests End of 5.0 tests
...@@ -1161,3 +1161,86 @@ t1 CREATE TABLE `t1` ( ...@@ -1161,3 +1161,86 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`c1`) PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
DROP TABLE t1; DROP TABLE t1;
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (-685113344), (1), (NULL), (NULL);
SELECT * FROM t1;
c1
-685113344
1
2
3
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (-685113344), (2), (NULL), (NULL);
SELECT * FROM t1;
c1
-685113344
2
3
4
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL), (2), (-685113344), (NULL);
INSERT INTO t1 VALUES (4), (5), (6), (NULL);
SELECT * FROM t1;
c1
-685113344
1
2
3
4
5
6
7
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL), (2), (-685113344), (5);
SELECT * FROM t1;
c1
-685113344
1
2
5
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1), (2), (-685113344), (NULL);
SELECT * FROM t1;
c1
-685113344
1
2
3
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
DROP TABLE t1;
...@@ -442,4 +442,30 @@ INSERT INTO t1 VALUES (1, 1), (2,2), (3, NULL); ...@@ -442,4 +442,30 @@ INSERT INTO t1 VALUES (1, 1), (2,2), (3, NULL);
SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL; SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug#50995 Having clause on subquery result produces incorrect results.
--echo #
CREATE TABLE t1
(
id1 INT,
id2 INT NOT NULL,
INDEX id1(id2)
);
INSERT INTO t1 SET id1=1, id2=1;
INSERT INTO t1 SET id1=2, id2=1;
INSERT INTO t1 SET id1=3, id2=1;
SELECT t1.id1,
(SELECT 0 FROM DUAL
WHERE t1.id1=t1.id1) AS amount FROM t1
WHERE t1.id2 = 1
HAVING amount > 0
ORDER BY t1.id1;
DROP TABLE t1;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -631,3 +631,34 @@ REPLACE INTO t1 VALUES (-1); ...@@ -631,3 +631,34 @@ REPLACE INTO t1 VALUES (-1);
SELECT * FROM t1; SELECT * FROM t1;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
DROP TABLE t1; DROP TABLE t1;
##
# 49497: Error 1467 (ER_AUTOINC_READ_FAILED) on inserting a negative value
#
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (-685113344), (1), (NULL), (NULL);
SELECT * FROM t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (-685113344), (2), (NULL), (NULL);
SELECT * FROM t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL), (2), (-685113344), (NULL);
INSERT INTO t1 VALUES (4), (5), (6), (NULL);
SELECT * FROM t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (NULL), (2), (-685113344), (5);
SELECT * FROM t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1), (2), (-685113344), (NULL);
SELECT * FROM t1;
SHOW CREATE TABLE t1;
DROP TABLE t1;
...@@ -1474,9 +1474,21 @@ class Item_cond :public Item_bool_func ...@@ -1474,9 +1474,21 @@ class Item_cond :public Item_bool_func
Item_cond(THD *thd, Item_cond *item); Item_cond(THD *thd, Item_cond *item);
Item_cond(List<Item> &nlist) Item_cond(List<Item> &nlist)
:Item_bool_func(), list(nlist), abort_on_null(0) {} :Item_bool_func(), list(nlist), abort_on_null(0) {}
bool add(Item *item) { return list.push_back(item); } bool add(Item *item)
bool add_at_head(Item *item) { return list.push_front(item); } {
void add_at_head(List<Item> *nlist) { list.prepand(nlist); } DBUG_ASSERT(item);
return list.push_back(item);
}
bool add_at_head(Item *item)
{
DBUG_ASSERT(item);
return list.push_front(item);
}
void add_at_head(List<Item> *nlist)
{
DBUG_ASSERT(nlist->elements);
list.prepand(nlist);
}
bool fix_fields(THD *, Item **ref); bool fix_fields(THD *, Item **ref);
enum Type type() const { return COND_ITEM; } enum Type type() const { return COND_ITEM; }
......
...@@ -8200,7 +8200,8 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, ...@@ -8200,7 +8200,8 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
else else
{ {
DBUG_ASSERT(cond->type() == Item::COND_ITEM); DBUG_ASSERT(cond->type() == Item::COND_ITEM);
((Item_cond *) cond)->add_at_head(&eq_list); if (eq_list.elements)
((Item_cond *) cond)->add_at_head(&eq_list);
} }
cond->quick_fix_field(); cond->quick_fix_field();
...@@ -15664,7 +15665,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) ...@@ -15664,7 +15665,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
Item_cond_and *cond=new Item_cond_and(); Item_cond_and *cond=new Item_cond_and();
TABLE *table=join_tab->table; TABLE *table=join_tab->table;
int error; int error= 0;
if (!cond) if (!cond)
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
...@@ -15682,7 +15683,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) ...@@ -15682,7 +15683,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
cond->fix_fields(thd, (Item**)&cond); cond->fix_fields(thd, (Item**)&cond);
if (join_tab->select) if (join_tab->select)
{ {
error=(int) cond->add(join_tab->select->cond); if (join_tab->select->cond)
error=(int) cond->add(join_tab->select->cond);
join_tab->select_cond=join_tab->select->cond=cond; join_tab->select_cond=join_tab->select->cond=cond;
} }
else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0, else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0,
......
...@@ -224,6 +224,9 @@ in the free list to the frames. ...@@ -224,6 +224,9 @@ in the free list to the frames.
/* Value in microseconds */ /* Value in microseconds */
static const int WAIT_FOR_READ = 20000; static const int WAIT_FOR_READ = 20000;
/* Number of attemtps made to read in a page in the buffer pool */
static const ulint BUF_PAGE_READ_MAX_RETRIES = 100;
buf_pool_t* buf_pool = NULL; /* The buffer buf_pool of the database */ buf_pool_t* buf_pool = NULL; /* The buffer buf_pool of the database */
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
...@@ -1160,6 +1163,7 @@ buf_page_get_gen( ...@@ -1160,6 +1163,7 @@ buf_page_get_gen(
ulint fix_type; ulint fix_type;
ibool success; ibool success;
ibool must_read; ibool must_read;
ulint retries = 0;
ut_ad(mtr); ut_ad(mtr);
ut_ad((rw_latch == RW_S_LATCH) ut_ad((rw_latch == RW_S_LATCH)
...@@ -1200,7 +1204,29 @@ buf_page_get_gen( ...@@ -1200,7 +1204,29 @@ buf_page_get_gen(
return(NULL); return(NULL);
} }
buf_read_page(space, offset); if (buf_read_page(space, offset)) {
retries = 0;
} else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
++retries;
} else {
fprintf(stderr, "InnoDB: Error: Unable"
" to read tablespace %lu page no"
" %lu into the buffer pool after"
" %lu attempts\n"
"InnoDB: The most probable cause"
" of this error may be that the"
" table has been corrupted.\n"
"InnoDB: You can try to fix this"
" problem by using"
" innodb_force_recovery.\n"
"InnoDB: Please see reference manual"
" for more details.\n"
"InnoDB: Aborting...\n",
space, offset,
BUF_PAGE_READ_MAX_RETRIES);
ut_error;
}
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
buf_dbg_counter++; buf_dbg_counter++;
......
...@@ -299,30 +299,27 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets ...@@ -299,30 +299,27 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock an exclusive lock on the buffer frame. The flag is cleared and the x-lock
released by the i/o-handler thread. Does a random read-ahead if it seems released by the i/o-handler thread. Does a random read-ahead if it seems
sensible. */ sensible. */
ibool
ulint
buf_read_page( buf_read_page(
/*==========*/ /*==========*/
/* out: number of page read requests issued: this can /* out: TRUE if success, FALSE otherwise */
be > 1 if read-ahead occurred */
ulint space, /* in: space id */ ulint space, /* in: space id */
ulint offset) /* in: page number */ ulint offset) /* in: page number */
{ {
ib_longlong tablespace_version; ib_longlong tablespace_version;
ulint count; ulint count;
ulint count2;
ulint err; ulint err;
tablespace_version = fil_space_get_version(space); tablespace_version = fil_space_get_version(space);
count = buf_read_ahead_random(space, offset); buf_read_ahead_random(space, offset);
/* We do the i/o in the synchronous aio mode to save thread /* We do the i/o in the synchronous aio mode to save thread
switches: hence TRUE */ switches: hence TRUE */
count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space, count = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
tablespace_version, offset); tablespace_version, offset);
srv_buf_pool_reads+= count2; srv_buf_pool_reads+= count;
if (err == DB_TABLESPACE_DELETED) { if (err == DB_TABLESPACE_DELETED) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
...@@ -336,7 +333,7 @@ buf_read_page( ...@@ -336,7 +333,7 @@ buf_read_page(
/* Flush pages from the end of the LRU list if necessary */ /* Flush pages from the end of the LRU list if necessary */
buf_flush_free_margin(); buf_flush_free_margin();
return(count + count2); return(count > 0);
} }
/************************************************************************ /************************************************************************
......
...@@ -2652,9 +2652,9 @@ ha_innobase::innobase_initialize_autoinc() ...@@ -2652,9 +2652,9 @@ ha_innobase::innobase_initialize_autoinc()
auto_inc = innobase_get_int_col_max_value(field); auto_inc = innobase_get_int_col_max_value(field);
} else { } else {
/* We have no idea what's been passed in to us as the /* We have no idea what's been passed in to us as the
autoinc column. We set it to the MAX_INT of our table autoinc column. We set it to the 0, effectively disabling
autoinc type. */ updates to the table. */
auto_inc = 0xFFFFFFFFFFFFFFFFULL; auto_inc = 0;
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Unable to determine the AUTOINC " fprintf(stderr, " InnoDB: Unable to determine the AUTOINC "
...@@ -2663,7 +2663,7 @@ ha_innobase::innobase_initialize_autoinc() ...@@ -2663,7 +2663,7 @@ ha_innobase::innobase_initialize_autoinc()
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
/* If the recovery level is set so high that writes /* If the recovery level is set so high that writes
are disabled we force the AUTOINC counter to the MAX are disabled we force the AUTOINC counter to 0
value effectively disabling writes to the table. value effectively disabling writes to the table.
Secondly, we avoid reading the table in case the read Secondly, we avoid reading the table in case the read
results in failure due to a corrupted table/index. results in failure due to a corrupted table/index.
...@@ -2672,7 +2672,10 @@ ha_innobase::innobase_initialize_autoinc() ...@@ -2672,7 +2672,10 @@ ha_innobase::innobase_initialize_autoinc()
tables can be dumped with minimal hassle. If an error tables can be dumped with minimal hassle. If an error
were returned in this case, the first attempt to read were returned in this case, the first attempt to read
the table would fail and subsequent SELECTs would succeed. */ the table would fail and subsequent SELECTs would succeed. */
auto_inc = 0;
} else if (field == NULL) { } else if (field == NULL) {
/* This is a far more serious error, best to avoid
opening the table and return failure. */
my_error(ER_AUTOINC_READ_FAILED, MYF(0)); my_error(ER_AUTOINC_READ_FAILED, MYF(0));
} else { } else {
dict_index_t* index; dict_index_t* index;
...@@ -2701,7 +2704,7 @@ ha_innobase::innobase_initialize_autoinc() ...@@ -2701,7 +2704,7 @@ ha_innobase::innobase_initialize_autoinc()
"InnoDB: Unable to find the AUTOINC column " "InnoDB: Unable to find the AUTOINC column "
"%s in the InnoDB table %s.\n" "%s in the InnoDB table %s.\n"
"InnoDB: We set the next AUTOINC column " "InnoDB: We set the next AUTOINC column "
"value to the maximum possible value,\n" "value to 0,\n"
"InnoDB: in effect disabling the AUTOINC " "InnoDB: in effect disabling the AUTOINC "
"next value generation.\n" "next value generation.\n"
"InnoDB: You can either set the next " "InnoDB: You can either set the next "
...@@ -2710,7 +2713,13 @@ ha_innobase::innobase_initialize_autoinc() ...@@ -2710,7 +2713,13 @@ ha_innobase::innobase_initialize_autoinc()
"recreating the table.\n", "recreating the table.\n",
col_name, index->table->name); col_name, index->table->name);
my_error(ER_AUTOINC_READ_FAILED, MYF(0)); /* This will disable the AUTOINC generation. */
auto_inc = 0;
/* We want the open to succeed, so that the user can
take corrective action. ie. reads should succeed but
updates should fail. */
err = DB_SUCCESS;
break; break;
default: default:
/* row_search_max_autoinc() should only return /* row_search_max_autoinc() should only return
...@@ -3968,11 +3977,17 @@ ha_innobase::write_row( ...@@ -3968,11 +3977,17 @@ ha_innobase::write_row(
prebuilt->autoinc_error = DB_SUCCESS; prebuilt->autoinc_error = DB_SUCCESS;
if ((error = update_auto_increment())) { if ((error = update_auto_increment())) {
/* We don't want to mask autoinc overflow errors. */ /* We don't want to mask autoinc overflow errors. */
if (prebuilt->autoinc_error != DB_SUCCESS) {
error = (int) prebuilt->autoinc_error;
/* Handle the case where the AUTOINC sub-system
failed during initialization. */
if (prebuilt->autoinc_error == DB_UNSUPPORTED) {
error_result = ER_AUTOINC_READ_FAILED;
/* Set the error message to report too. */
my_error(ER_AUTOINC_READ_FAILED, MYF(0));
goto func_exit;
} else if (prebuilt->autoinc_error != DB_SUCCESS) {
error = (int) prebuilt->autoinc_error;
goto report_error; goto report_error;
} }
...@@ -7883,7 +7898,10 @@ ha_innobase::innobase_get_autoinc( ...@@ -7883,7 +7898,10 @@ ha_innobase::innobase_get_autoinc(
*value = dict_table_autoinc_read(prebuilt->table); *value = dict_table_autoinc_read(prebuilt->table);
/* It should have been initialized during open. */ /* It should have been initialized during open. */
ut_a(*value != 0); if (*value == 0) {
prebuilt->autoinc_error = DB_UNSUPPORTED;
dict_table_autoinc_unlock(prebuilt->table);
}
} }
return(ulong(prebuilt->autoinc_error)); return(ulong(prebuilt->autoinc_error));
...@@ -7963,6 +7981,11 @@ ha_innobase::get_auto_increment( ...@@ -7963,6 +7981,11 @@ ha_innobase::get_auto_increment(
invoking this method. So we are not sure if it's guaranteed to invoking this method. So we are not sure if it's guaranteed to
be 0 or not. */ be 0 or not. */
/* We need the upper limit of the col type to check for
whether we update the table autoinc counter or not. */
ulonglong col_max_value = innobase_get_int_col_max_value(
table->next_number_field);
/* Called for the first time ? */ /* Called for the first time ? */
if (trx->n_autoinc_rows == 0) { if (trx->n_autoinc_rows == 0) {
...@@ -7979,6 +8002,11 @@ ha_innobase::get_auto_increment( ...@@ -7979,6 +8002,11 @@ ha_innobase::get_auto_increment(
/* Not in the middle of a mult-row INSERT. */ /* Not in the middle of a mult-row INSERT. */
} else if (prebuilt->autoinc_last_value == 0) { } else if (prebuilt->autoinc_last_value == 0) {
set_if_bigger(*first_value, autoinc); set_if_bigger(*first_value, autoinc);
/* Check for -ve values. */
} else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) {
/* Set to next logical value. */
ut_a(autoinc > trx->n_autoinc_rows);
*first_value = (autoinc - trx->n_autoinc_rows) - 1;
} }
*nb_reserved_values = trx->n_autoinc_rows; *nb_reserved_values = trx->n_autoinc_rows;
...@@ -7989,12 +8017,6 @@ ha_innobase::get_auto_increment( ...@@ -7989,12 +8017,6 @@ ha_innobase::get_auto_increment(
ulonglong need; ulonglong need;
ulonglong current; ulonglong current;
ulonglong next_value; ulonglong next_value;
ulonglong col_max_value;
/* We need the upper limit of the col type to check for
whether we update the table autoinc counter or not. */
col_max_value = innobase_get_int_col_max_value(
table->next_number_field);
current = *first_value > col_max_value ? autoinc : *first_value; current = *first_value > col_max_value ? autoinc : *first_value;
need = *nb_reserved_values * increment; need = *nb_reserved_values * increment;
......
...@@ -18,12 +18,10 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets ...@@ -18,12 +18,10 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock an exclusive lock on the buffer frame. The flag is cleared and the x-lock
released by the i/o-handler thread. Does a random read-ahead if it seems released by the i/o-handler thread. Does a random read-ahead if it seems
sensible. */ sensible. */
ibool
ulint
buf_read_page( buf_read_page(
/*==========*/ /*==========*/
/* out: number of page read requests issued: this can /* out: TRUE if success, FALSE otherwise */
be > 1 if read-ahead occurred */
ulint space, /* in: space id */ ulint space, /* in: space id */
ulint offset);/* in: page number */ ulint offset);/* in: page number */
/************************************************************************ /************************************************************************
......
...@@ -306,6 +306,7 @@ FILE* lock_latest_err_file; ...@@ -306,6 +306,7 @@ FILE* lock_latest_err_file;
/* Flags for recursive deadlock search */ /* Flags for recursive deadlock search */
#define LOCK_VICTIM_IS_START 1 #define LOCK_VICTIM_IS_START 1
#define LOCK_VICTIM_IS_OTHER 2 #define LOCK_VICTIM_IS_OTHER 2
#define LOCK_EXCEED_MAX_DEPTH 3
/************************************************************************ /************************************************************************
Checks if a lock request results in a deadlock. */ Checks if a lock request results in a deadlock. */
...@@ -332,16 +333,18 @@ lock_deadlock_recursive( ...@@ -332,16 +333,18 @@ lock_deadlock_recursive(
was found and we chose some other trx as a was found and we chose some other trx as a
victim: we must do the search again in this victim: we must do the search again in this
last case because there may be another last case because there may be another
deadlock! */ deadlock!
LOCK_EXCEED_MAX_DEPTH if the lock search
exceeds max steps and/or max depth. */
trx_t* start, /* in: recursion starting point */ trx_t* start, /* in: recursion starting point */
trx_t* trx, /* in: a transaction waiting for a lock */ trx_t* trx, /* in: a transaction waiting for a lock */
lock_t* wait_lock, /* in: the lock trx is waiting to be granted */ lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
ulint* cost, /* in/out: number of calculation steps thus ulint* cost, /* in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_... far: if this exceeds LOCK_MAX_N_STEPS_...
we return LOCK_VICTIM_IS_START */ we return LOCK_EXCEED_MAX_DEPTH */
ulint depth); /* in: recursion depth: if this exceeds ulint depth); /* in: recursion depth: if this exceeds
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
return LOCK_VICTIM_IS_START */ return LOCK_EXCEED_MAX_DEPTH */
/************************************************************************* /*************************************************************************
Gets the nth bit of a record lock. */ Gets the nth bit of a record lock. */
...@@ -3084,8 +3087,6 @@ lock_deadlock_occurs( ...@@ -3084,8 +3087,6 @@ lock_deadlock_occurs(
lock_t* lock, /* in: lock the transaction is requesting */ lock_t* lock, /* in: lock the transaction is requesting */
trx_t* trx) /* in: transaction */ trx_t* trx) /* in: transaction */
{ {
dict_table_t* table;
dict_index_t* index;
trx_t* mark_trx; trx_t* mark_trx;
ulint ret; ulint ret;
ulint cost = 0; ulint cost = 0;
...@@ -3107,31 +3108,50 @@ lock_deadlock_occurs( ...@@ -3107,31 +3108,50 @@ lock_deadlock_occurs(
ret = lock_deadlock_recursive(trx, trx, lock, &cost, 0); ret = lock_deadlock_recursive(trx, trx, lock, &cost, 0);
if (ret == LOCK_VICTIM_IS_OTHER) { switch (ret) {
case LOCK_VICTIM_IS_OTHER:
/* We chose some other trx as a victim: retry if there still /* We chose some other trx as a victim: retry if there still
is a deadlock */ is a deadlock */
goto retry; goto retry;
}
if (ret == LOCK_VICTIM_IS_START) { case LOCK_EXCEED_MAX_DEPTH:
if (lock_get_type(lock) & LOCK_TABLE) { /* If the lock search exceeds the max step
table = lock->un_member.tab_lock.table; or the max depth, the current trx will be
index = NULL; the victim. Print its information. */
rewind(lock_latest_err_file);
ut_print_timestamp(lock_latest_err_file);
fputs("TOO DEEP OR LONG SEARCH IN THE LOCK TABLE"
" WAITS-FOR GRAPH, WE WILL ROLL BACK"
" FOLLOWING TRANSACTION \n",
lock_latest_err_file);
fputs("\n*** TRANSACTION:\n", lock_latest_err_file);
trx_print(lock_latest_err_file, trx, 3000);
fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n",
lock_latest_err_file);
if (lock_get_type(lock) == LOCK_REC) {
lock_rec_print(lock_latest_err_file, lock);
} else { } else {
index = lock->index; lock_table_print(lock_latest_err_file, lock);
table = index->table;
} }
break;
lock_deadlock_found = TRUE; case LOCK_VICTIM_IS_START:
fputs("*** WE ROLL BACK TRANSACTION (2)\n", fputs("*** WE ROLL BACK TRANSACTION (2)\n",
lock_latest_err_file); lock_latest_err_file);
break;
return(TRUE); default:
/* No deadlock detected*/
return(FALSE);
} }
return(FALSE); lock_deadlock_found = TRUE;
return(TRUE);
} }
/************************************************************************ /************************************************************************
...@@ -3147,16 +3167,18 @@ lock_deadlock_recursive( ...@@ -3147,16 +3167,18 @@ lock_deadlock_recursive(
was found and we chose some other trx as a was found and we chose some other trx as a
victim: we must do the search again in this victim: we must do the search again in this
last case because there may be another last case because there may be another
deadlock! */ deadlock!
LOCK_EXCEED_MAX_DEPTH if the lock search
exceeds max steps and/or max depth. */
trx_t* start, /* in: recursion starting point */ trx_t* start, /* in: recursion starting point */
trx_t* trx, /* in: a transaction waiting for a lock */ trx_t* trx, /* in: a transaction waiting for a lock */
lock_t* wait_lock, /* in: the lock trx is waiting to be granted */ lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
ulint* cost, /* in/out: number of calculation steps thus ulint* cost, /* in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_... far: if this exceeds LOCK_MAX_N_STEPS_...
we return LOCK_VICTIM_IS_START */ we return LOCK_EXCEED_MAX_DEPTH */
ulint depth) /* in: recursion depth: if this exceeds ulint depth) /* in: recursion depth: if this exceeds
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
return LOCK_VICTIM_IS_START */ return LOCK_EXCEED_MAX_DEPTH */
{ {
lock_t* lock; lock_t* lock;
ulint bit_no = ULINT_UNDEFINED; ulint bit_no = ULINT_UNDEFINED;
...@@ -3215,7 +3237,7 @@ lock_deadlock_recursive( ...@@ -3215,7 +3237,7 @@ lock_deadlock_recursive(
lock_trx = lock->trx; lock_trx = lock->trx;
if (lock_trx == start || too_far) { if (lock_trx == start) {
/* We came back to the recursion starting /* We came back to the recursion starting
point: a deadlock detected; or we have point: a deadlock detected; or we have
...@@ -3262,19 +3284,10 @@ lock_deadlock_recursive( ...@@ -3262,19 +3284,10 @@ lock_deadlock_recursive(
} }
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
if (lock_print_waits) { if (lock_print_waits) {
fputs("Deadlock detected" fputs("Deadlock detected\n",
" or too long search\n",
stderr); stderr);
} }
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
if (too_far) {
fputs("TOO DEEP OR LONG SEARCH"
" IN THE LOCK TABLE"
" WAITS-FOR GRAPH\n", ef);
return(LOCK_VICTIM_IS_START);
}
if (trx_weight_cmp(wait_lock->trx, if (trx_weight_cmp(wait_lock->trx,
start) >= 0) { start) >= 0) {
...@@ -3310,6 +3323,21 @@ lock_deadlock_recursive( ...@@ -3310,6 +3323,21 @@ lock_deadlock_recursive(
return(LOCK_VICTIM_IS_OTHER); return(LOCK_VICTIM_IS_OTHER);
} }
if (too_far) {
#ifdef UNIV_DEBUG
if (lock_print_waits) {
fputs("Deadlock search exceeds"
" max steps or depth.\n",
stderr);
}
#endif /* UNIV_DEBUG */
/* The information about transaction/lock
to be rolled back is available in the top
level. Do not print anything here. */
return(LOCK_EXCEED_MAX_DEPTH);
}
if (lock_trx->que_state == TRX_QUE_LOCK_WAIT) { if (lock_trx->que_state == TRX_QUE_LOCK_WAIT) {
/* Another trx ahead has requested lock in an /* Another trx ahead has requested lock in an
......
...@@ -759,7 +759,15 @@ os_file_readdir_next_file( ...@@ -759,7 +759,15 @@ os_file_readdir_next_file(
#ifdef HAVE_READDIR_R #ifdef HAVE_READDIR_R
ret = readdir_r(dir, (struct dirent*)dirent_buf, &ent); ret = readdir_r(dir, (struct dirent*)dirent_buf, &ent);
if (ret != 0) { if (ret != 0
#ifdef UNIV_AIX
/* On AIX, only if we got non-NULL 'ent' (result) value and
a non-zero 'ret' (return) value, it indicates a failed
readdir_r() call. An NULL 'ent' with an non-zero 'ret'
would indicate the "end of the directory" is reached. */
&& ent != NULL
#endif
) {
fprintf(stderr, fprintf(stderr,
"InnoDB: cannot read directory %s, error %lu\n", "InnoDB: cannot read directory %s, error %lu\n",
dirname, (ulong)ret); dirname, (ulong)ret);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment