Skip to content

Commit cf1110c

Browse files
author
Jon Olav Hauglid
committed
Backport of revno: 3702
Bug #48248 assert in MDL_ticket::upgrade_shared_lock_to_exclusive The assert would happen if REPAIR TABLE was used on a table already locked by LOCK TABLES READ. REPAIR mistakenly tried to upgrade the read-lock to exclusive, thereby triggering the assert. The cause of the problem was that REPAIR TABLE ignored errors from opening and locking tables. This is by design, as REPAIR can be used to broken tables that cannot be opened. However, repair also ignored logical errors such as the inability to exclusivly lock a table due to conflicting LOCK TABLES. This patch fixes the problem by not ignoring errors from opening and locking tables if inside LOCK TABLES mode. In LOCK TABLES we already know that the table can be opened, so that the failure to open must be a logical error. Test added to repair.test.
1 parent 81813b1 commit cf1110c

File tree

5 files changed

+44
-6
lines changed

5 files changed

+44
-6
lines changed

mysql-test/r/lock.result

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ lock tables t1 write;
4141
check table t2;
4242
Table Op Msg_type Msg_text
4343
test.t2 check Error Table 't2' was not locked with LOCK TABLES
44-
test.t2 check error Corrupt
44+
test.t2 check status Operation failed
4545
insert into t1 select index1,nr from t1;
4646
ERROR HY000: Table 't1' was not locked with LOCK TABLES
4747
unlock tables;

mysql-test/r/repair.result

+12
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,15 @@ REPAIR TABLE tt1 USE_FRM;
157157
Table Op Msg_type Msg_text
158158
tt1 repair error Cannot repair temporary table from .frm file
159159
DROP TABLE tt1;
160+
#
161+
# Bug #48248 assert in MDL_ticket::upgrade_shared_lock_to_exclusive
162+
#
163+
DROP TABLE IF EXISTS t1;
164+
CREATE TABLE t1(a INT);
165+
LOCK TABLES t1 READ;
166+
REPAIR TABLE t1;
167+
Table Op Msg_type Msg_text
168+
test.t1 repair Error Table 't1' was locked with a READ lock and can't be updated
169+
test.t1 repair status Operation failed
170+
UNLOCK TABLES;
171+
DROP TABLE t1;

mysql-test/r/view.result

+3-3
Original file line numberDiff line numberDiff line change
@@ -1955,15 +1955,15 @@ CHECK TABLE v1, v2, v3, v4, v5, v6;
19551955
Table Op Msg_type Msg_text
19561956
test.v1 check Error FUNCTION test.f1 does not exist
19571957
test.v1 check Error View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
1958-
test.v1 check error Corrupt
1958+
test.v1 check status Operation failed
19591959
test.v2 check status OK
19601960
test.v3 check Error FUNCTION test.f1 does not exist
19611961
test.v3 check Error View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
1962-
test.v3 check error Corrupt
1962+
test.v3 check status Operation failed
19631963
test.v4 check status OK
19641964
test.v5 check Error FUNCTION test.f1 does not exist
19651965
test.v5 check Error View 'test.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
1966-
test.v5 check error Corrupt
1966+
test.v5 check status Operation failed
19671967
test.v6 check status OK
19681968
create function f1 () returns int return (select max(col1) from t1);
19691969
DROP TABLE t1;

mysql-test/t/repair.test

+15
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,18 @@ CREATE TEMPORARY TABLE tt1 (c1 INT);
158158
REPAIR TABLE tt1 USE_FRM;
159159
DROP TABLE tt1;
160160

161+
162+
--echo #
163+
--echo # Bug #48248 assert in MDL_ticket::upgrade_shared_lock_to_exclusive
164+
--echo #
165+
166+
--disable_warnings
167+
DROP TABLE IF EXISTS t1;
168+
--enable_warnings
169+
170+
CREATE TABLE t1(a INT);
171+
LOCK TABLES t1 READ;
172+
REPAIR TABLE t1;
173+
174+
UNLOCK TABLES;
175+
DROP TABLE t1;

sql/sql_table.cc

+13-2
Original file line numberDiff line numberDiff line change
@@ -4548,6 +4548,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
45484548
char table_name[NAME_LEN*2+2];
45494549
char* db = table->db;
45504550
bool fatal_error=0;
4551+
bool open_error;
45514552

45524553
DBUG_PRINT("admin", ("table: '%s'.'%s'", table->db, table->table_name));
45534554
DBUG_PRINT("admin", ("extra_open_options: %u", extra_open_options));
@@ -4575,12 +4576,22 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
45754576
if (view_operator_func == NULL)
45764577
table->required_type=FRMTYPE_TABLE;
45774578

4578-
open_and_lock_tables_derived(thd, table, TRUE,
4579-
MYSQL_OPEN_TAKE_UPGRADABLE_MDL);
4579+
open_error= open_and_lock_tables_derived(thd, table, TRUE,
4580+
MYSQL_OPEN_TAKE_UPGRADABLE_MDL);
45804581
thd->no_warnings_for_error= 0;
45814582
table->next_global= save_next_global;
45824583
table->next_local= save_next_local;
45834584
thd->open_options&= ~extra_open_options;
4585+
/*
4586+
Under locked tables, we know that the table can be opened,
4587+
so any errors opening the table are logical errors.
4588+
In these cases it does not make sense to try to repair.
4589+
*/
4590+
if (open_error && thd->locked_tables_mode)
4591+
{
4592+
result_code= HA_ADMIN_FAILED;
4593+
goto send_result;
4594+
}
45844595
#ifdef WITH_PARTITION_STORAGE_ENGINE
45854596
if (table->table)
45864597
{

0 commit comments

Comments
 (0)