mirror of
https://github.com/MariaDB/server.git
synced 2026-04-20 15:25:33 +02:00
Fix race condition in ANALYZE TABLE.
Fixed bug where one got an empty set instead of a DEADLOCK error when using BDB tables. Docs/manual.texi: Cleanup configure.in: Version number change mysql-test/t/backup.test: drop used tables mysql-test/t/bdb-crash.test: cleanup mysys/thr_lock.c: cleanup sql/mysqld.cc: safety fix sql/records.cc: Fixed bug where one got an empty set instead of a DEADLOCK error when using BDB tables. sql/sql_table.cc: Fix race condition in ANALYZE TABLE.
This commit is contained in:
parent
7ef7d93726
commit
4615e50093
10 changed files with 121 additions and 24 deletions
|
|
@ -46785,6 +46785,7 @@ users use this code as the rest of the code and because of this we are
|
|||
not yet 100% confident in this code.
|
||||
|
||||
@menu
|
||||
* News-3.23.46::
|
||||
* News-3.23.45:: Changes in release 3.23.45
|
||||
* News-3.23.44:: Changes in release 3.23.44
|
||||
* News-3.23.43:: Changes in release 3.23.43
|
||||
|
|
@ -46834,7 +46835,20 @@ not yet 100% confident in this code.
|
|||
* News-3.23.0:: Changes in release 3.23.0
|
||||
@end menu
|
||||
|
||||
@node News-3.23.45, News-3.23.44, News-3.23.x, News-3.23.x
|
||||
@node News-3.23.46, News-3.23.45, News-3.23.x, News-3.23.x
|
||||
@appendixsubsec Changes in release 3.23.46
|
||||
@itemize @bullet
|
||||
@item
|
||||
Fixed bug where one got an empty set instead of a DEADLOCK error when using
|
||||
BDB tables.
|
||||
@item
|
||||
One can now kill @code{ANALYZE},@code{REPAIR} and @code{OPTIMIZE TABLE} when
|
||||
the thread is waiting to get a lock on the table.
|
||||
@item
|
||||
Fixed race condition in @code{ANALYZE TABLE}.
|
||||
@end itemize
|
||||
|
||||
@node News-3.23.45, News-3.23.44, News-3.23.46, News-3.23.x
|
||||
@appendixsubsec Changes in release 3.23.45
|
||||
@itemize @bullet
|
||||
@item
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script.
|
|||
AC_INIT(sql/mysqld.cc)
|
||||
AC_CANONICAL_SYSTEM
|
||||
# The Docs Makefile.am parses this line!
|
||||
AM_INIT_AUTOMAKE(mysql, 3.23.45)
|
||||
AM_INIT_AUTOMAKE(mysql, 3.23.46)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
PROTOCOL_VERSION=10
|
||||
|
|
|
|||
10
mysql-test/r/bdb-deadlock.result
Normal file
10
mysql-test/r/bdb-deadlock.result
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
x
|
||||
1
|
||||
id x
|
||||
0 1
|
||||
id x
|
||||
0 1
|
||||
id x
|
||||
0 1
|
||||
id x
|
||||
0 1
|
||||
|
|
@ -39,6 +39,7 @@ reap;
|
|||
unlock tables;
|
||||
connection con1;
|
||||
reap;
|
||||
drop table t1;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# test for bug reported by Mark Steele
|
||||
|
||||
drop table if exists tblChange;
|
||||
CREATE TABLE tblCharge (
|
||||
drop table if exists t1;
|
||||
CREATE TABLE t1 (
|
||||
ChargeID int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
|
||||
ServiceID int(10) unsigned DEFAULT '0' NOT NULL,
|
||||
ChargeDate date DEFAULT '0000-00-00' NOT NULL,
|
||||
|
|
@ -19,16 +19,16 @@ DEFAULT 'New' NOT NULL,
|
|||
) type=BDB;
|
||||
|
||||
BEGIN;
|
||||
INSERT INTO tblCharge
|
||||
INSERT INTO t1
|
||||
VALUES(NULL,1,'2001-03-01',1,1,1,'New',NULL,NULL,'now');
|
||||
COMMIT;
|
||||
|
||||
BEGIN;
|
||||
UPDATE tblCharge SET ChargeAuthorizationMessage = 'blablabla' WHERE
|
||||
UPDATE t1 SET ChargeAuthorizationMessage = 'blablabla' WHERE
|
||||
ChargeID = 1;
|
||||
COMMIT;
|
||||
|
||||
INSERT INTO tblCharge
|
||||
INSERT INTO t1
|
||||
VALUES(NULL,1,'2001-03-01',1,1,1,'New',NULL,NULL,'now');
|
||||
select * from tblCharge;
|
||||
drop table tblCharge;
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
|
|
|||
48
mysql-test/t/bdb-deadlock.test
Normal file
48
mysql-test/t/bdb-deadlock.test
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# This test doesn't work with the embedded version as this code
|
||||
# assumes that one query is running while we are doing queries on
|
||||
# a second connection.
|
||||
# This would work if mysqltest run would be threaded and handle each
|
||||
# connection in a separate thread.
|
||||
#
|
||||
|
||||
#-- source include/not_embedded.inc
|
||||
-- source include/have_bdb.inc
|
||||
|
||||
connect (con1,localhost,root,,);
|
||||
connect (con2,localhost,root,,);
|
||||
|
||||
drop table if exists t1,t2;
|
||||
connection con1;
|
||||
create table t1 (id integer, x integer) type=BDB;
|
||||
create table t2 (id integer, x integer) type=BDB;
|
||||
insert into t1 values(0, 0);
|
||||
insert into t2 values(0, 0);
|
||||
set autocommit=0;
|
||||
update t1 set x = 1 where id = 0;
|
||||
|
||||
connection con2;
|
||||
set autocommit=0;
|
||||
update t2 set x = 1 where id = 0;
|
||||
|
||||
# The following query should hang because con1 is locking the page
|
||||
--send
|
||||
select x from t1 where id = 0;
|
||||
|
||||
connection con1;
|
||||
# This should generate a deadlock as we are trying to access a locked row
|
||||
--error 1213
|
||||
select x from t2 where id = 0;
|
||||
commit;
|
||||
|
||||
connection con2;
|
||||
reap;
|
||||
commit;
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
commit;
|
||||
|
||||
connection con1;
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
commit;
|
||||
drop table t1,t2;
|
||||
|
|
@ -913,7 +913,8 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count)
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/* Abort all threads waiting for a lock. The lock will be upgraded to a
|
||||
/*
|
||||
Abort all threads waiting for a lock. The lock will be upgraded to
|
||||
TL_WRITE_ONLY to abort any new accesses to the lock
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -718,8 +718,8 @@ void clean_up(bool print_message)
|
|||
if (!opt_noacl)
|
||||
udf_free();
|
||||
#endif
|
||||
end_key_cache();
|
||||
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
|
||||
end_key_cache();
|
||||
#ifdef USE_RAID
|
||||
end_raid();
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -132,8 +132,13 @@ static int rr_quick(READ_RECORD *info)
|
|||
{
|
||||
if (tmp == HA_ERR_END_OF_FILE)
|
||||
tmp= -1;
|
||||
else if (info->print_error)
|
||||
info->file->print_error(tmp,MYF(0));
|
||||
else
|
||||
{
|
||||
if (info->print_error)
|
||||
info->file->print_error(tmp,MYF(0));
|
||||
if (tmp < 0) // Fix negative BDB errno
|
||||
tmp=1;
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
|
@ -153,8 +158,13 @@ static int rr_sequential(READ_RECORD *info)
|
|||
{
|
||||
if (tmp == HA_ERR_END_OF_FILE)
|
||||
tmp= -1;
|
||||
else if (info->print_error)
|
||||
info->table->file->print_error(tmp,MYF(0));
|
||||
else
|
||||
{
|
||||
if (info->print_error)
|
||||
info->table->file->print_error(tmp,MYF(0));
|
||||
if (tmp < 0) // Fix negative BDB errno
|
||||
tmp=1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -168,21 +178,27 @@ static int rr_from_tempfile(READ_RECORD *info)
|
|||
tryNext:
|
||||
if (my_b_read(info->io_cache,info->ref_pos,info->ref_length))
|
||||
return -1; /* End of file */
|
||||
tmp=info->file->rnd_pos(info->record,info->ref_pos);
|
||||
if (tmp)
|
||||
if ((tmp=info->file->rnd_pos(info->record,info->ref_pos)))
|
||||
{
|
||||
if (tmp == HA_ERR_END_OF_FILE)
|
||||
tmp= -1;
|
||||
else if (tmp == HA_ERR_RECORD_DELETED)
|
||||
goto tryNext;
|
||||
else if (info->print_error)
|
||||
info->file->print_error(tmp,MYF(0));
|
||||
else
|
||||
{
|
||||
if (info->print_error)
|
||||
info->file->print_error(tmp,MYF(0));
|
||||
if (tmp < 0) // Fix negative BDB errno
|
||||
tmp=1;
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
} /* rr_from_tempfile */
|
||||
|
||||
|
||||
static int rr_from_pointers(READ_RECORD *info)
|
||||
{
|
||||
int tmp;
|
||||
byte *cache_pos;
|
||||
tryNext:
|
||||
if (info->cache_pos == info->cache_end)
|
||||
|
|
@ -190,15 +206,19 @@ tryNext:
|
|||
cache_pos=info->cache_pos;
|
||||
info->cache_pos+=info->ref_length;
|
||||
|
||||
int tmp=info->file->rnd_pos(info->record,cache_pos);
|
||||
if (tmp)
|
||||
if ((tmp=info->file->rnd_pos(info->record,cache_pos)))
|
||||
{
|
||||
if (tmp == HA_ERR_END_OF_FILE)
|
||||
tmp= -1;
|
||||
else if (tmp == HA_ERR_RECORD_DELETED)
|
||||
goto tryNext;
|
||||
else if (info->print_error)
|
||||
info->file->print_error(tmp,MYF(0));
|
||||
else
|
||||
{
|
||||
if (info->print_error)
|
||||
info->file->print_error(tmp,MYF(0));
|
||||
if (tmp < 0) // Fix negative BDB errno
|
||||
tmp=1;
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -964,9 +964,11 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
|||
}
|
||||
|
||||
/* Close all instances of the table to allow repair to rename files */
|
||||
if (open_for_modify && table->table->version)
|
||||
if (lock_type == TL_WRITE && table->table->version)
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
|
||||
"Waiting to get writelock");
|
||||
mysql_lock_abort(thd,table->table);
|
||||
while (remove_table_from_cache(thd, table->table->table_cache_key,
|
||||
table->table->real_name) &&
|
||||
|
|
@ -976,6 +978,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
|||
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
|
||||
dropping_tables--;
|
||||
}
|
||||
thd->exit_cond(old_message);
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
if (thd->killed)
|
||||
goto err;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue