mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 02:51:44 +01:00
merging from 5.1-bt rep to local branch
This commit is contained in:
commit
57d6b44400
12 changed files with 325 additions and 72 deletions
|
@ -430,4 +430,24 @@ SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL;
|
|||
b COUNT(DISTINCT a)
|
||||
NULL 1
|
||||
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
|
||||
|
|
|
@ -1161,3 +1161,86 @@ t1 CREATE TABLE `t1` (
|
|||
PRIMARY KEY (`c1`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
|
||||
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);
|
|||
SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL;
|
||||
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
|
||||
|
|
|
@ -631,3 +631,34 @@ REPLACE INTO t1 VALUES (-1);
|
|||
SELECT * FROM t1;
|
||||
SHOW CREATE 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 @@ public:
|
|||
Item_cond(THD *thd, Item_cond *item);
|
||||
Item_cond(List<Item> &nlist)
|
||||
:Item_bool_func(), list(nlist), abort_on_null(0) {}
|
||||
bool add(Item *item) { return list.push_back(item); }
|
||||
bool add_at_head(Item *item) { return list.push_front(item); }
|
||||
void add_at_head(List<Item> *nlist) { list.prepand(nlist); }
|
||||
bool add(Item *item)
|
||||
{
|
||||
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);
|
||||
|
||||
enum Type type() const { return COND_ITEM; }
|
||||
|
|
|
@ -8200,7 +8200,8 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
|
|||
else
|
||||
{
|
||||
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();
|
||||
|
@ -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();
|
||||
TABLE *table=join_tab->table;
|
||||
int error;
|
||||
int error= 0;
|
||||
if (!cond)
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
|
@ -15682,7 +15683,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
|
|||
cond->fix_fields(thd, (Item**)&cond);
|
||||
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;
|
||||
}
|
||||
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.
|
|||
/* Value in microseconds */
|
||||
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 */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
|
@ -1160,6 +1163,7 @@ buf_page_get_gen(
|
|||
ulint fix_type;
|
||||
ibool success;
|
||||
ibool must_read;
|
||||
ulint retries = 0;
|
||||
|
||||
ut_ad(mtr);
|
||||
ut_ad((rw_latch == RW_S_LATCH)
|
||||
|
@ -1200,7 +1204,29 @@ loop:
|
|||
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
|
||||
buf_dbg_counter++;
|
||||
|
|
|
@ -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
|
||||
released by the i/o-handler thread. Does a random read-ahead if it seems
|
||||
sensible. */
|
||||
|
||||
ulint
|
||||
ibool
|
||||
buf_read_page(
|
||||
/*==========*/
|
||||
/* out: number of page read requests issued: this can
|
||||
be > 1 if read-ahead occurred */
|
||||
/* out: TRUE if success, FALSE otherwise */
|
||||
ulint space, /* in: space id */
|
||||
ulint offset) /* in: page number */
|
||||
{
|
||||
ib_longlong tablespace_version;
|
||||
ulint count;
|
||||
ulint count2;
|
||||
ulint err;
|
||||
|
||||
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
|
||||
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);
|
||||
srv_buf_pool_reads+= count2;
|
||||
srv_buf_pool_reads+= count;
|
||||
if (err == DB_TABLESPACE_DELETED) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
|
@ -336,7 +333,7 @@ buf_read_page(
|
|||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin();
|
||||
|
||||
return(count + count2);
|
||||
return(count > 0);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
|
|
@ -2652,9 +2652,9 @@ ha_innobase::innobase_initialize_autoinc()
|
|||
auto_inc = innobase_get_int_col_max_value(field);
|
||||
} else {
|
||||
/* 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 type. */
|
||||
auto_inc = 0xFFFFFFFFFFFFFFFFULL;
|
||||
autoinc column. We set it to the 0, effectively disabling
|
||||
updates to the table. */
|
||||
auto_inc = 0;
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB: Unable to determine the AUTOINC "
|
||||
|
@ -2663,7 +2663,7 @@ ha_innobase::innobase_initialize_autoinc()
|
|||
|
||||
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
|
||||
/* 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.
|
||||
Secondly, we avoid reading the table in case the read
|
||||
results in failure due to a corrupted table/index.
|
||||
|
@ -2672,7 +2672,10 @@ ha_innobase::innobase_initialize_autoinc()
|
|||
tables can be dumped with minimal hassle. If an error
|
||||
were returned in this case, the first attempt to read
|
||||
the table would fail and subsequent SELECTs would succeed. */
|
||||
auto_inc = 0;
|
||||
} 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));
|
||||
} else {
|
||||
dict_index_t* index;
|
||||
|
@ -2701,7 +2704,7 @@ ha_innobase::innobase_initialize_autoinc()
|
|||
"InnoDB: Unable to find the AUTOINC column "
|
||||
"%s in the InnoDB table %s.\n"
|
||||
"InnoDB: We set the next AUTOINC column "
|
||||
"value to the maximum possible value,\n"
|
||||
"value to 0,\n"
|
||||
"InnoDB: in effect disabling the AUTOINC "
|
||||
"next value generation.\n"
|
||||
"InnoDB: You can either set the next "
|
||||
|
@ -2710,7 +2713,13 @@ ha_innobase::innobase_initialize_autoinc()
|
|||
"recreating the table.\n",
|
||||
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;
|
||||
default:
|
||||
/* row_search_max_autoinc() should only return
|
||||
|
@ -3968,11 +3977,17 @@ no_commit:
|
|||
prebuilt->autoinc_error = DB_SUCCESS;
|
||||
|
||||
if ((error = update_auto_increment())) {
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -7883,7 +7898,10 @@ ha_innobase::innobase_get_autoinc(
|
|||
*value = dict_table_autoinc_read(prebuilt->table);
|
||||
|
||||
/* 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));
|
||||
|
@ -7963,6 +7981,11 @@ ha_innobase::get_auto_increment(
|
|||
invoking this method. So we are not sure if it's guaranteed to
|
||||
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 ? */
|
||||
if (trx->n_autoinc_rows == 0) {
|
||||
|
||||
|
@ -7979,6 +8002,11 @@ ha_innobase::get_auto_increment(
|
|||
/* Not in the middle of a mult-row INSERT. */
|
||||
} else if (prebuilt->autoinc_last_value == 0) {
|
||||
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;
|
||||
|
@ -7989,12 +8017,6 @@ ha_innobase::get_auto_increment(
|
|||
ulonglong need;
|
||||
ulonglong current;
|
||||
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;
|
||||
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
|
|||
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
|
||||
sensible. */
|
||||
|
||||
ulint
|
||||
ibool
|
||||
buf_read_page(
|
||||
/*==========*/
|
||||
/* out: number of page read requests issued: this can
|
||||
be > 1 if read-ahead occurred */
|
||||
/* out: TRUE if success, FALSE otherwise */
|
||||
ulint space, /* in: space id */
|
||||
ulint offset);/* in: page number */
|
||||
/************************************************************************
|
||||
|
|
|
@ -306,6 +306,7 @@ FILE* lock_latest_err_file;
|
|||
/* Flags for recursive deadlock search */
|
||||
#define LOCK_VICTIM_IS_START 1
|
||||
#define LOCK_VICTIM_IS_OTHER 2
|
||||
#define LOCK_EXCEED_MAX_DEPTH 3
|
||||
|
||||
/************************************************************************
|
||||
Checks if a lock request results in a deadlock. */
|
||||
|
@ -332,16 +333,18 @@ lock_deadlock_recursive(
|
|||
was found and we chose some other trx as a
|
||||
victim: we must do the search again in this
|
||||
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* trx, /* in: a transaction waiting for a lock */
|
||||
lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
|
||||
ulint* cost, /* in/out: number of calculation steps thus
|
||||
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
|
||||
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. */
|
||||
|
@ -3084,8 +3087,6 @@ lock_deadlock_occurs(
|
|||
lock_t* lock, /* in: lock the transaction is requesting */
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
dict_table_t* table;
|
||||
dict_index_t* index;
|
||||
trx_t* mark_trx;
|
||||
ulint ret;
|
||||
ulint cost = 0;
|
||||
|
@ -3107,31 +3108,50 @@ retry:
|
|||
|
||||
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
|
||||
is a deadlock */
|
||||
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (ret == LOCK_VICTIM_IS_START) {
|
||||
if (lock_get_type(lock) & LOCK_TABLE) {
|
||||
table = lock->un_member.tab_lock.table;
|
||||
index = NULL;
|
||||
} else {
|
||||
index = lock->index;
|
||||
table = index->table;
|
||||
}
|
||||
case LOCK_EXCEED_MAX_DEPTH:
|
||||
/* If the lock search exceeds the max step
|
||||
or the max depth, the current trx will be
|
||||
the victim. Print its information. */
|
||||
rewind(lock_latest_err_file);
|
||||
ut_print_timestamp(lock_latest_err_file);
|
||||
|
||||
lock_deadlock_found = TRUE;
|
||||
|
||||
fputs("*** WE ROLL BACK TRANSACTION (2)\n",
|
||||
fputs("TOO DEEP OR LONG SEARCH IN THE LOCK TABLE"
|
||||
" WAITS-FOR GRAPH, WE WILL ROLL BACK"
|
||||
" FOLLOWING TRANSACTION \n",
|
||||
lock_latest_err_file);
|
||||
|
||||
return(TRUE);
|
||||
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 {
|
||||
lock_table_print(lock_latest_err_file, lock);
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCK_VICTIM_IS_START:
|
||||
fputs("*** WE ROLL BACK TRANSACTION (2)\n",
|
||||
lock_latest_err_file);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* No deadlock detected*/
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
lock_deadlock_found = TRUE;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
@ -3147,16 +3167,18 @@ lock_deadlock_recursive(
|
|||
was found and we chose some other trx as a
|
||||
victim: we must do the search again in this
|
||||
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* trx, /* in: a transaction waiting for a lock */
|
||||
lock_t* wait_lock, /* in: the lock trx is waiting to be granted */
|
||||
ulint* cost, /* in/out: number of calculation steps thus
|
||||
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
|
||||
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
|
||||
return LOCK_VICTIM_IS_START */
|
||||
return LOCK_EXCEED_MAX_DEPTH */
|
||||
{
|
||||
lock_t* lock;
|
||||
ulint bit_no = ULINT_UNDEFINED;
|
||||
|
@ -3215,7 +3237,7 @@ lock_deadlock_recursive(
|
|||
|
||||
lock_trx = lock->trx;
|
||||
|
||||
if (lock_trx == start || too_far) {
|
||||
if (lock_trx == start) {
|
||||
|
||||
/* We came back to the recursion starting
|
||||
point: a deadlock detected; or we have
|
||||
|
@ -3262,19 +3284,10 @@ lock_deadlock_recursive(
|
|||
}
|
||||
#ifdef UNIV_DEBUG
|
||||
if (lock_print_waits) {
|
||||
fputs("Deadlock detected"
|
||||
" or too long search\n",
|
||||
fputs("Deadlock detected\n",
|
||||
stderr);
|
||||
}
|
||||
#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,
|
||||
start) >= 0) {
|
||||
|
@ -3310,6 +3323,21 @@ lock_deadlock_recursive(
|
|||
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) {
|
||||
|
||||
/* Another trx ahead has requested lock in an
|
||||
|
|
|
@ -759,7 +759,15 @@ next_file:
|
|||
#ifdef HAVE_READDIR_R
|
||||
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,
|
||||
"InnoDB: cannot read directory %s, error %lu\n",
|
||||
dirname, (ulong)ret);
|
||||
|
|
Loading…
Add table
Reference in a new issue