merge 5.1->5.1-security.
This commit is contained in:
commit
ba788ec90e
@ -57,7 +57,7 @@ LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
|
|||||||
char *batch_readline(LINE_BUFFER *line_buff)
|
char *batch_readline(LINE_BUFFER *line_buff)
|
||||||
{
|
{
|
||||||
char *pos;
|
char *pos;
|
||||||
ulong out_length;
|
ulong out_length= 0;
|
||||||
|
|
||||||
if (!(pos=intern_read_line(line_buff, &out_length)))
|
if (!(pos=intern_read_line(line_buff, &out_length)))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -43,7 +43,12 @@
|
|||||||
#define LIBEDIT_MAJOR 2
|
#define LIBEDIT_MAJOR 2
|
||||||
#define LIBEDIT_MINOR 11
|
#define LIBEDIT_MINOR 11
|
||||||
|
|
||||||
|
/* XXXMYSQL : stdint.h might not be available on older Solaris platforms. */
|
||||||
|
#if defined(__sun) || defined(__sun__)
|
||||||
|
#include <sys/inttypes.h>
|
||||||
|
#else
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -47,14 +47,21 @@ static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93";
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
/* XXXMYSQL : stdint.h might not be available on older Solaris platforms. */
|
||||||
|
#if defined(__sun) || defined(__sun__)
|
||||||
|
#include <sys/inttypes.h>
|
||||||
|
#else
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#ifdef HAVE_VIS_H
|
/*
|
||||||
#include <vis.h>
|
XXXMYSQL : Due to different versions of vis.h available,
|
||||||
#else
|
use the one bundled with libedit.
|
||||||
|
*/
|
||||||
#include "np/vis.h"
|
#include "np/vis.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __weak_alias
|
#ifdef __weak_alias
|
||||||
__weak_alias(strnunvisx,_strnunvisx)
|
__weak_alias(strnunvisx,_strnunvisx)
|
||||||
|
@ -68,11 +68,11 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#ifdef HAVE_VIS_H
|
/*
|
||||||
#include <vis.h>
|
XXXMYSQL : Due to different versions of vis.h available,
|
||||||
#else
|
use the one bundled with libedit.
|
||||||
|
*/
|
||||||
#include "np/vis.h"
|
#include "np/vis.h"
|
||||||
#endif
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@ -333,7 +333,7 @@ memset(&state, 0, sizeof(mbstate_t));
|
|||||||
|
|
||||||
#ifdef WIDECHAR
|
#ifdef WIDECHAR
|
||||||
++cbp;
|
++cbp;
|
||||||
if (cbp > MB_CUR_MAX) { /* "shouldn't happen" */
|
if (cbp > (size_t) MB_CUR_MAX) { /* "shouldn't happen" */
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
/*
|
/* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -12,8 +11,7 @@
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _my_stacktrace_h_
|
#ifndef _my_stacktrace_h_
|
||||||
#define _my_stacktrace_h_
|
#define _my_stacktrace_h_
|
||||||
@ -63,6 +61,69 @@ void my_set_exception_pointers(EXCEPTION_POINTERS *ep);
|
|||||||
void my_write_core(int sig);
|
void my_write_core(int sig);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Async-signal-safe utility functions used by signal handler routines.
|
||||||
|
Declared here in order to unit-test them.
|
||||||
|
These are not general-purpose, but tailored to the signal handling routines.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
Converts a longlong value to string.
|
||||||
|
@param base 10 for decimal, 16 for hex values (0..9a..f)
|
||||||
|
@param val The value to convert
|
||||||
|
@param buf Assumed to point to the *end* of the buffer.
|
||||||
|
@returns Pointer to the first character of the converted string.
|
||||||
|
Negative values:
|
||||||
|
for base-10 the return string will be prepended with '-'
|
||||||
|
for base-16 the return string will contain 16 characters
|
||||||
|
Implemented with simplicity, and async-signal-safety in mind.
|
||||||
|
*/
|
||||||
|
char *my_safe_itoa(int base, longlong val, char *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts a ulonglong value to string.
|
||||||
|
@param base 10 for decimal, 16 for hex values (0..9a..f)
|
||||||
|
@param val The value to convert
|
||||||
|
@param buf Assumed to point to the *end* of the buffer.
|
||||||
|
@returns Pointer to the first character of the converted string.
|
||||||
|
Implemented with simplicity, and async-signal-safety in mind.
|
||||||
|
*/
|
||||||
|
char *my_safe_utoa(int base, ulonglong val, char *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
A (very) limited version of snprintf.
|
||||||
|
@param to Destination buffer.
|
||||||
|
@param n Size of destination buffer.
|
||||||
|
@param fmt printf() style format string.
|
||||||
|
@returns Number of bytes written, including terminating '\0'
|
||||||
|
Supports 'd' 'i' 'u' 'x' 'p' 's' conversion.
|
||||||
|
Supports 'l' and 'll' modifiers for integral types.
|
||||||
|
Does not support any width/precision.
|
||||||
|
Implemented with simplicity, and async-signal-safety in mind.
|
||||||
|
*/
|
||||||
|
size_t my_safe_snprintf(char* to, size_t n, const char* fmt, ...)
|
||||||
|
ATTRIBUTE_FORMAT(printf, 3, 4);
|
||||||
|
|
||||||
|
/**
|
||||||
|
A (very) limited version of snprintf, which writes the result to STDERR.
|
||||||
|
@sa my_safe_snprintf
|
||||||
|
Implemented with simplicity, and async-signal-safety in mind.
|
||||||
|
@note Has an internal buffer capacity of 512 bytes,
|
||||||
|
which should suffice for our signal handling routines.
|
||||||
|
*/
|
||||||
|
size_t my_safe_printf_stderr(const char* fmt, ...)
|
||||||
|
ATTRIBUTE_FORMAT(printf, 1, 2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Writes up to count bytes from buffer to STDERR.
|
||||||
|
Implemented with simplicity, and async-signal-safety in mind.
|
||||||
|
@param buf Buffer containing data to be written.
|
||||||
|
@param count Number of bytes to write.
|
||||||
|
@returns Number of bytes written.
|
||||||
|
*/
|
||||||
|
size_t my_write_stderr(const void *buf, size_t count);
|
||||||
|
|
||||||
C_MODE_END
|
C_MODE_END
|
||||||
|
|
||||||
#endif /* _my_stacktrace_h_ */
|
#endif /* _my_stacktrace_h_ */
|
||||||
|
@ -109,6 +109,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
|
|||||||
../sql/password.c ../sql/discover.cc ../sql/derror.cc
|
../sql/password.c ../sql/discover.cc ../sql/derror.cc
|
||||||
../sql/field.cc ../sql/field_conv.cc
|
../sql/field.cc ../sql/field_conv.cc
|
||||||
../sql/filesort.cc ../sql/gstream.cc ../sql/ha_partition.cc
|
../sql/filesort.cc ../sql/gstream.cc ../sql/ha_partition.cc
|
||||||
|
../sql/signal_handler.cc
|
||||||
../sql/handler.cc ../sql/hash_filo.cc ../sql/hostname.cc
|
../sql/handler.cc ../sql/hash_filo.cc ../sql/hostname.cc
|
||||||
../sql/init.cc ../sql/item_buff.cc ../sql/item_cmpfunc.cc
|
../sql/init.cc ../sql/item_buff.cc ../sql/item_cmpfunc.cc
|
||||||
../sql/item.cc ../sql/item_create.cc ../sql/item_func.cc
|
../sql/item.cc ../sql/item_create.cc ../sql/item_func.cc
|
||||||
|
@ -12772,3 +12772,22 @@ a b c d e f
|
|||||||
-1 b c d e 1
|
-1 b c d e 1
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
SET sort_buffer_size=DEFAULT;
|
SET sort_buffer_size=DEFAULT;
|
||||||
|
#
|
||||||
|
# BUG#11758979 - 51252: ARCHIVE TABLES CAUSE 100% CPU USAGE
|
||||||
|
# AND HANG IN SHOW TABLE STATUS
|
||||||
|
# (to be executed with valgrind)
|
||||||
|
CREATE TABLE t1(a BLOB, b VARCHAR(200)) ENGINE=ARCHIVE;
|
||||||
|
INSERT INTO t1 VALUES(NULL, '');
|
||||||
|
FLUSH TABLE t1;
|
||||||
|
# we need this select to workaround BUG#11764364
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
NULL
|
||||||
|
CHECKSUM TABLE t1 EXTENDED;
|
||||||
|
Table Checksum
|
||||||
|
test.t1 286155052
|
||||||
|
FLUSH TABLE t1;
|
||||||
|
OPTIMIZE TABLE t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 optimize status OK
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -55,3 +55,20 @@ id x
|
|||||||
1 1
|
1 1
|
||||||
2 10
|
2 10
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
#Bug#12842206 INNODB LOCKING REGRESSION FOR INSERT IGNORE
|
||||||
|
#fixed by re-fixing Bug#7975
|
||||||
|
#aka Bug#11759688 52020: InnoDB can still deadlock on just INSERT...
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES(3,1);
|
||||||
|
BEGIN;
|
||||||
|
INSERT IGNORE INTO t1 VALUES(3,14);
|
||||||
|
BEGIN;
|
||||||
|
INSERT IGNORE INTO t1 VALUES(3,23);
|
||||||
|
SELECT * FROM t1 FOR UPDATE;
|
||||||
|
COMMIT;
|
||||||
|
a b
|
||||||
|
3 1
|
||||||
|
COMMIT;
|
||||||
|
DROP TABLE t1;
|
||||||
|
77
mysql-test/suite/innodb/r/innodb_replace.result
Normal file
77
mysql-test/suite/innodb/r/innodb_replace.result
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#
|
||||||
|
#Bug#11759688 52020: InnoDB can still deadlock
|
||||||
|
#on just INSERT...ON DUPLICATE KEY
|
||||||
|
#a.k.a. Bug#7975 deadlock without any locking, simple select and update
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES(3,1);
|
||||||
|
BEGIN;
|
||||||
|
SET DEBUG_SYNC='write_row_noreplace SIGNAL insert1 WAIT_FOR select1';
|
||||||
|
INSERT INTO t1 VALUES(3,2);
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert1';
|
||||||
|
SELECT * FROM t1 LOCK IN SHARE MODE;
|
||||||
|
a b
|
||||||
|
3 1
|
||||||
|
SELECT * FROM t1 FOR UPDATE;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select1';
|
||||||
|
ERROR 23000: Duplicate entry '3' for key 'PRIMARY'
|
||||||
|
INSERT INTO t1 VALUES(3,3) ON DUPLICATE KEY UPDATE b=b+10;
|
||||||
|
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||||
|
COMMIT;
|
||||||
|
SET DEBUG_SYNC='write_row_replace SIGNAL insert2 WAIT_FOR select2';
|
||||||
|
REPLACE INTO t1 VALUES(3,4);
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert2';
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
3 11
|
||||||
|
SELECT * FROM t1 LOCK IN SHARE MODE;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select2';
|
||||||
|
SET DEBUG_SYNC='write_row_replace SIGNAL insert3 WAIT_FOR select3';
|
||||||
|
INSERT INTO t1 VALUES(3,5) ON DUPLICATE KEY UPDATE b=b+20;
|
||||||
|
a b
|
||||||
|
3 4
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert3';
|
||||||
|
SELECT b FROM t1 LOCK IN SHARE MODE;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select3';
|
||||||
|
b
|
||||||
|
24
|
||||||
|
SET DEBUG_SYNC='write_row_noreplace SIGNAL insert4 WAIT_FOR select4';
|
||||||
|
LOAD DATA INFILE '../../std_data/loaddata5.dat' INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b);
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert4';
|
||||||
|
SELECT b FROM t1 WHERE a=3 LOCK IN SHARE MODE;
|
||||||
|
b
|
||||||
|
24
|
||||||
|
SELECT b FROM t1 WHERE a=3 FOR UPDATE;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select4';
|
||||||
|
b
|
||||||
|
24
|
||||||
|
ERROR 23000: Duplicate entry '3' for key 'PRIMARY'
|
||||||
|
SET DEBUG_SYNC='write_row_noreplace SIGNAL insert5 WAIT_FOR select5';
|
||||||
|
LOAD DATA INFILE '../../std_data/loaddata5.dat' IGNORE INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b);
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert5';
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
3 24
|
||||||
|
SELECT * FROM t1 WHERE a=3 LOCK IN SHARE MODE;
|
||||||
|
a b
|
||||||
|
3 24
|
||||||
|
SELECT * FROM t1 WHERE a=3 FOR UPDATE;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select5';
|
||||||
|
a b
|
||||||
|
3 24
|
||||||
|
SET DEBUG_SYNC='write_row_replace SIGNAL insert6 WAIT_FOR select6';
|
||||||
|
LOAD DATA INFILE '../../std_data/loaddata5.dat' REPLACE INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b);
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert6';
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
3 24
|
||||||
|
5 6
|
||||||
|
SELECT a,b FROM t1 LOCK IN SHARE MODE;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select6';
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
3 4
|
||||||
|
5 6
|
||||||
|
SET DEBUG_SYNC='RESET';
|
||||||
|
DROP TABLE t1;
|
@ -100,3 +100,44 @@ select * from t1;
|
|||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo #Bug#12842206 INNODB LOCKING REGRESSION FOR INSERT IGNORE
|
||||||
|
--echo #fixed by re-fixing Bug#7975
|
||||||
|
--echo #aka Bug#11759688 52020: InnoDB can still deadlock on just INSERT...
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES(3,1);
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
# this used to wrongly acquire an X lock; now it takes an S lock
|
||||||
|
INSERT IGNORE INTO t1 VALUES(3,14);
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
BEGIN;
|
||||||
|
# this used to wrongly acquire an X lock; now it takes an S lock
|
||||||
|
INSERT IGNORE INTO t1 VALUES(3,23);
|
||||||
|
--send
|
||||||
|
SELECT * FROM t1 FOR UPDATE;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
# Check that the above SELECT is blocked
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'Sending data' and
|
||||||
|
info = 'SELECT * FROM t1 FOR UPDATE';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
COMMIT;
|
||||||
|
connection con1;
|
||||||
|
reap;
|
||||||
|
COMMIT;
|
||||||
|
disconnect con1;
|
||||||
|
disconnect con2;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
DROP TABLE t1;
|
||||||
|
186
mysql-test/suite/innodb/t/innodb_replace.test
Normal file
186
mysql-test/suite/innodb/t/innodb_replace.test
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
--source include/have_innodb.inc
|
||||||
|
--source include/have_debug_sync.inc
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo #Bug#11759688 52020: InnoDB can still deadlock
|
||||||
|
--echo #on just INSERT...ON DUPLICATE KEY
|
||||||
|
--echo #a.k.a. Bug#7975 deadlock without any locking, simple select and update
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES(3,1);
|
||||||
|
|
||||||
|
connect (con1,localhost,root,,);
|
||||||
|
connect (con2,localhost,root,,);
|
||||||
|
connection con1;
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
# normal INSERT of a duplicate should only S-lock the existing record (3,1)
|
||||||
|
SET DEBUG_SYNC='write_row_noreplace SIGNAL insert1 WAIT_FOR select1';
|
||||||
|
--send
|
||||||
|
INSERT INTO t1 VALUES(3,2);
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert1';
|
||||||
|
# this should S-lock (3,1); no conflict
|
||||||
|
SELECT * FROM t1 LOCK IN SHARE MODE;
|
||||||
|
# this should X-lock (3,1), conflicting with con1
|
||||||
|
--send
|
||||||
|
SELECT * FROM t1 FOR UPDATE;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
# Check that the above SELECT is blocked
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'Sending data' and
|
||||||
|
info = 'SELECT * FROM t1 FOR UPDATE';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select1';
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
--error ER_DUP_ENTRY
|
||||||
|
reap;
|
||||||
|
# We are still holding an S-lock on (3,1) after the failed INSERT.
|
||||||
|
# The following will upgrade it to an X-lock, causing a deadlock.
|
||||||
|
# InnoDB should resolve the deadlock by aborting the blocked SELECT.
|
||||||
|
INSERT INTO t1 VALUES(3,3) ON DUPLICATE KEY UPDATE b=b+10;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
--error ER_LOCK_DEADLOCK
|
||||||
|
reap;
|
||||||
|
connection con1;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
SET DEBUG_SYNC='write_row_replace SIGNAL insert2 WAIT_FOR select2';
|
||||||
|
--send
|
||||||
|
REPLACE INTO t1 VALUES(3,4);
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert2';
|
||||||
|
SELECT * FROM t1;
|
||||||
|
--send
|
||||||
|
SELECT * FROM t1 LOCK IN SHARE MODE;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
# Check that the above SELECT is blocked because of X lock.
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'Sending data' and
|
||||||
|
info = 'SELECT * FROM t1 LOCK IN SHARE MODE';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select2';
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
reap;
|
||||||
|
|
||||||
|
SET DEBUG_SYNC='write_row_replace SIGNAL insert3 WAIT_FOR select3';
|
||||||
|
--send
|
||||||
|
INSERT INTO t1 VALUES(3,5) ON DUPLICATE KEY UPDATE b=b+20;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
reap;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert3';
|
||||||
|
--send
|
||||||
|
SELECT b FROM t1 LOCK IN SHARE MODE;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
# Check that the above SELECT is blocked because of X lock.
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'Sending data' and
|
||||||
|
info = 'SELECT b FROM t1 LOCK IN SHARE MODE';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select3';
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
reap;
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
reap;
|
||||||
|
SET DEBUG_SYNC='write_row_noreplace SIGNAL insert4 WAIT_FOR select4';
|
||||||
|
--send
|
||||||
|
LOAD DATA INFILE '../../std_data/loaddata5.dat' INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b);
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert4';
|
||||||
|
# this should S-lock (3,1); no conflict
|
||||||
|
SELECT b FROM t1 WHERE a=3 LOCK IN SHARE MODE;
|
||||||
|
# this should X-lock (3,1), conflicting with con1
|
||||||
|
--send
|
||||||
|
SELECT b FROM t1 WHERE a=3 FOR UPDATE;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
# Check that the above SELECT is blocked
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'statistics' and
|
||||||
|
info = 'SELECT b FROM t1 WHERE a=3 FOR UPDATE';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select4';
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
reap;
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
--error ER_DUP_ENTRY
|
||||||
|
reap;
|
||||||
|
SET DEBUG_SYNC='write_row_noreplace SIGNAL insert5 WAIT_FOR select5';
|
||||||
|
--send
|
||||||
|
LOAD DATA INFILE '../../std_data/loaddata5.dat' IGNORE INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b);
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert5';
|
||||||
|
SELECT * FROM t1;
|
||||||
|
# this should S-lock; no conflict
|
||||||
|
SELECT * FROM t1 WHERE a=3 LOCK IN SHARE MODE;
|
||||||
|
# this should X-lock, conflicting with the S-lock of the IGNORE in con1
|
||||||
|
--send
|
||||||
|
SELECT * FROM t1 WHERE a=3 FOR UPDATE;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
# Check that the above SELECT is blocked
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'statistics' and
|
||||||
|
info = 'SELECT * FROM t1 WHERE a=3 FOR UPDATE';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select5';
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
reap;
|
||||||
|
connection default;
|
||||||
|
reap;
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
SET DEBUG_SYNC='write_row_replace SIGNAL insert6 WAIT_FOR select6';
|
||||||
|
--send
|
||||||
|
LOAD DATA INFILE '../../std_data/loaddata5.dat' REPLACE INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b);
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert6';
|
||||||
|
SELECT * FROM t1;
|
||||||
|
# this should conflict with the X-lock acquired by the REPLACE
|
||||||
|
--send
|
||||||
|
SELECT a,b FROM t1 LOCK IN SHARE MODE;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
# Check that the above SELECT is blocked
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'Sending data' and
|
||||||
|
info = 'SELECT a,b FROM t1 LOCK IN SHARE MODE';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select6';
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
reap;
|
||||||
|
connection default;
|
||||||
|
reap;
|
||||||
|
|
||||||
|
disconnect con1;
|
||||||
|
disconnect con2;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC='RESET';
|
||||||
|
DROP TABLE t1;
|
@ -55,3 +55,20 @@ id x
|
|||||||
1 1
|
1 1
|
||||||
2 10
|
2 10
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
#Bug#12842206 INNODB LOCKING REGRESSION FOR INSERT IGNORE
|
||||||
|
#fixed by re-fixing Bug#7975
|
||||||
|
#aka Bug#11759688 52020: InnoDB can still deadlock on just INSERT...
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES(3,1);
|
||||||
|
BEGIN;
|
||||||
|
INSERT IGNORE INTO t1 VALUES(3,14);
|
||||||
|
BEGIN;
|
||||||
|
INSERT IGNORE INTO t1 VALUES(3,23);
|
||||||
|
SELECT * FROM t1 FOR UPDATE;
|
||||||
|
COMMIT;
|
||||||
|
a b
|
||||||
|
3 1
|
||||||
|
COMMIT;
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
set global innodb_file_per_table=on;
|
||||||
|
set global innodb_file_format=`1`;
|
||||||
|
create table t1(a text) engine=innodb key_block_size=8;
|
||||||
|
SELECT page_size FROM information_schema.innodb_cmpmem WHERE pages_used > 0;
|
||||||
|
page_size
|
||||||
|
8192
|
||||||
|
drop table t1;
|
||||||
|
SELECT page_size FROM information_schema.innodb_cmpmem WHERE pages_used > 0;
|
||||||
|
page_size
|
||||||
|
create table t2(a text) engine=innodb;
|
||||||
|
SELECT page_size FROM information_schema.innodb_cmpmem WHERE pages_used > 0;
|
||||||
|
page_size
|
||||||
|
drop table t2;
|
77
mysql-test/suite/innodb_plugin/r/innodb_replace.result
Normal file
77
mysql-test/suite/innodb_plugin/r/innodb_replace.result
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#
|
||||||
|
#Bug#11759688 52020: InnoDB can still deadlock
|
||||||
|
#on just INSERT...ON DUPLICATE KEY
|
||||||
|
#a.k.a. Bug#7975 deadlock without any locking, simple select and update
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 VALUES(3,1);
|
||||||
|
BEGIN;
|
||||||
|
SET DEBUG_SYNC='write_row_noreplace SIGNAL insert1 WAIT_FOR select1';
|
||||||
|
INSERT INTO t1 VALUES(3,2);
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert1';
|
||||||
|
SELECT * FROM t1 LOCK IN SHARE MODE;
|
||||||
|
a b
|
||||||
|
3 1
|
||||||
|
SELECT * FROM t1 FOR UPDATE;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select1';
|
||||||
|
ERROR 23000: Duplicate entry '3' for key 'PRIMARY'
|
||||||
|
INSERT INTO t1 VALUES(3,3) ON DUPLICATE KEY UPDATE b=b+10;
|
||||||
|
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||||
|
COMMIT;
|
||||||
|
SET DEBUG_SYNC='write_row_replace SIGNAL insert2 WAIT_FOR select2';
|
||||||
|
REPLACE INTO t1 VALUES(3,4);
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert2';
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
3 11
|
||||||
|
SELECT * FROM t1 LOCK IN SHARE MODE;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select2';
|
||||||
|
SET DEBUG_SYNC='write_row_replace SIGNAL insert3 WAIT_FOR select3';
|
||||||
|
INSERT INTO t1 VALUES(3,5) ON DUPLICATE KEY UPDATE b=b+20;
|
||||||
|
a b
|
||||||
|
3 4
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert3';
|
||||||
|
SELECT b FROM t1 LOCK IN SHARE MODE;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select3';
|
||||||
|
b
|
||||||
|
24
|
||||||
|
SET DEBUG_SYNC='write_row_noreplace SIGNAL insert4 WAIT_FOR select4';
|
||||||
|
LOAD DATA INFILE '../../std_data/loaddata5.dat' INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b);
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert4';
|
||||||
|
SELECT b FROM t1 WHERE a=3 LOCK IN SHARE MODE;
|
||||||
|
b
|
||||||
|
24
|
||||||
|
SELECT b FROM t1 WHERE a=3 FOR UPDATE;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select4';
|
||||||
|
b
|
||||||
|
24
|
||||||
|
ERROR 23000: Duplicate entry '3' for key 'PRIMARY'
|
||||||
|
SET DEBUG_SYNC='write_row_noreplace SIGNAL insert5 WAIT_FOR select5';
|
||||||
|
LOAD DATA INFILE '../../std_data/loaddata5.dat' IGNORE INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b);
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert5';
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
3 24
|
||||||
|
SELECT * FROM t1 WHERE a=3 LOCK IN SHARE MODE;
|
||||||
|
a b
|
||||||
|
3 24
|
||||||
|
SELECT * FROM t1 WHERE a=3 FOR UPDATE;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select5';
|
||||||
|
a b
|
||||||
|
3 24
|
||||||
|
SET DEBUG_SYNC='write_row_replace SIGNAL insert6 WAIT_FOR select6';
|
||||||
|
LOAD DATA INFILE '../../std_data/loaddata5.dat' REPLACE INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b);
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert6';
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
3 24
|
||||||
|
5 6
|
||||||
|
SELECT a,b FROM t1 LOCK IN SHARE MODE;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select6';
|
||||||
|
a b
|
||||||
|
1 2
|
||||||
|
3 4
|
||||||
|
5 6
|
||||||
|
SET DEBUG_SYNC='RESET';
|
||||||
|
DROP TABLE t1;
|
@ -100,3 +100,44 @@ select * from t1;
|
|||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo #Bug#12842206 INNODB LOCKING REGRESSION FOR INSERT IGNORE
|
||||||
|
--echo #fixed by re-fixing Bug#7975
|
||||||
|
--echo #aka Bug#11759688 52020: InnoDB can still deadlock on just INSERT...
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES(3,1);
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
# this used to wrongly acquire an X lock; now it takes an S lock
|
||||||
|
INSERT IGNORE INTO t1 VALUES(3,14);
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
BEGIN;
|
||||||
|
# this used to wrongly acquire an X lock; now it takes an S lock
|
||||||
|
INSERT IGNORE INTO t1 VALUES(3,23);
|
||||||
|
--send
|
||||||
|
SELECT * FROM t1 FOR UPDATE;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
# Check that the above SELECT is blocked
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'Sending data' and
|
||||||
|
info = 'SELECT * FROM t1 FOR UPDATE';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
COMMIT;
|
||||||
|
connection con1;
|
||||||
|
reap;
|
||||||
|
COMMIT;
|
||||||
|
disconnect con1;
|
||||||
|
disconnect con2;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
--innodb-buffer-pool-size=8M
|
59
mysql-test/suite/innodb_plugin/t/innodb_cmp_drop_table.test
Normal file
59
mysql-test/suite/innodb_plugin/t/innodb_cmp_drop_table.test
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
-- source include/have_innodb_plugin.inc
|
||||||
|
|
||||||
|
let $per_table=`select @@innodb_file_per_table`;
|
||||||
|
let $format=`select @@innodb_file_format`;
|
||||||
|
|
||||||
|
-- let $query_i_s = SELECT page_size FROM information_schema.innodb_cmpmem WHERE pages_used > 0
|
||||||
|
|
||||||
|
set global innodb_file_per_table=on;
|
||||||
|
set global innodb_file_format=`1`;
|
||||||
|
|
||||||
|
create table t1(a text) engine=innodb key_block_size=8;
|
||||||
|
|
||||||
|
-- disable_query_log
|
||||||
|
|
||||||
|
# insert some rows so we are using compressed pages
|
||||||
|
-- let $i = 10
|
||||||
|
while ($i)
|
||||||
|
{
|
||||||
|
insert into t1 values(repeat('abcdefghijklmnopqrstuvwxyz',100));
|
||||||
|
dec $i;
|
||||||
|
}
|
||||||
|
-- enable_query_log
|
||||||
|
|
||||||
|
# we should be using some 8K pages
|
||||||
|
-- eval $query_i_s
|
||||||
|
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
# no lazy eviction at drop table in 5.1 there should still be no
|
||||||
|
# used 8K pages
|
||||||
|
-- eval $query_i_s
|
||||||
|
|
||||||
|
# create a non-compressed table and insert enough into it to evict
|
||||||
|
# compressed pages
|
||||||
|
create table t2(a text) engine=innodb;
|
||||||
|
|
||||||
|
-- disable_query_log
|
||||||
|
|
||||||
|
-- let $i = 200
|
||||||
|
while ($i)
|
||||||
|
{
|
||||||
|
insert into t2 values(repeat('abcdefghijklmnopqrstuvwxyz',1000));
|
||||||
|
dec $i;
|
||||||
|
}
|
||||||
|
|
||||||
|
-- enable_query_log
|
||||||
|
|
||||||
|
# now there should be no 8K pages in the buffer pool
|
||||||
|
-- eval $query_i_s
|
||||||
|
|
||||||
|
drop table t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# restore environment to the state it was before this test execution
|
||||||
|
#
|
||||||
|
|
||||||
|
-- disable_query_log
|
||||||
|
eval set global innodb_file_format=$format;
|
||||||
|
eval set global innodb_file_per_table=$per_table;
|
186
mysql-test/suite/innodb_plugin/t/innodb_replace.test
Normal file
186
mysql-test/suite/innodb_plugin/t/innodb_replace.test
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
--source include/have_innodb_plugin.inc
|
||||||
|
--source include/have_debug_sync.inc
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo #Bug#11759688 52020: InnoDB can still deadlock
|
||||||
|
--echo #on just INSERT...ON DUPLICATE KEY
|
||||||
|
--echo #a.k.a. Bug#7975 deadlock without any locking, simple select and update
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY, b INT NOT NULL) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES(3,1);
|
||||||
|
|
||||||
|
connect (con1,localhost,root,,);
|
||||||
|
connect (con2,localhost,root,,);
|
||||||
|
connection con1;
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
# normal INSERT of a duplicate should only S-lock the existing record (3,1)
|
||||||
|
SET DEBUG_SYNC='write_row_noreplace SIGNAL insert1 WAIT_FOR select1';
|
||||||
|
--send
|
||||||
|
INSERT INTO t1 VALUES(3,2);
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert1';
|
||||||
|
# this should S-lock (3,1); no conflict
|
||||||
|
SELECT * FROM t1 LOCK IN SHARE MODE;
|
||||||
|
# this should X-lock (3,1), conflicting with con1
|
||||||
|
--send
|
||||||
|
SELECT * FROM t1 FOR UPDATE;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
# Check that the above SELECT is blocked
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'Sending data' and
|
||||||
|
info = 'SELECT * FROM t1 FOR UPDATE';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select1';
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
--error ER_DUP_ENTRY
|
||||||
|
reap;
|
||||||
|
# We are still holding an S-lock on (3,1) after the failed INSERT.
|
||||||
|
# The following will upgrade it to an X-lock, causing a deadlock.
|
||||||
|
# InnoDB should resolve the deadlock by aborting the blocked SELECT.
|
||||||
|
INSERT INTO t1 VALUES(3,3) ON DUPLICATE KEY UPDATE b=b+10;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
--error ER_LOCK_DEADLOCK
|
||||||
|
reap;
|
||||||
|
connection con1;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
SET DEBUG_SYNC='write_row_replace SIGNAL insert2 WAIT_FOR select2';
|
||||||
|
--send
|
||||||
|
REPLACE INTO t1 VALUES(3,4);
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert2';
|
||||||
|
SELECT * FROM t1;
|
||||||
|
--send
|
||||||
|
SELECT * FROM t1 LOCK IN SHARE MODE;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
# Check that the above SELECT is blocked because of X lock.
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'Sending data' and
|
||||||
|
info = 'SELECT * FROM t1 LOCK IN SHARE MODE';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select2';
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
reap;
|
||||||
|
|
||||||
|
SET DEBUG_SYNC='write_row_replace SIGNAL insert3 WAIT_FOR select3';
|
||||||
|
--send
|
||||||
|
INSERT INTO t1 VALUES(3,5) ON DUPLICATE KEY UPDATE b=b+20;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
reap;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert3';
|
||||||
|
--send
|
||||||
|
SELECT b FROM t1 LOCK IN SHARE MODE;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
# Check that the above SELECT is blocked because of X lock.
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'Sending data' and
|
||||||
|
info = 'SELECT b FROM t1 LOCK IN SHARE MODE';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select3';
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
reap;
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
reap;
|
||||||
|
SET DEBUG_SYNC='write_row_noreplace SIGNAL insert4 WAIT_FOR select4';
|
||||||
|
--send
|
||||||
|
LOAD DATA INFILE '../../std_data/loaddata5.dat' INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b);
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert4';
|
||||||
|
# this should S-lock (3,1); no conflict
|
||||||
|
SELECT b FROM t1 WHERE a=3 LOCK IN SHARE MODE;
|
||||||
|
# this should X-lock (3,1), conflicting with con1
|
||||||
|
--send
|
||||||
|
SELECT b FROM t1 WHERE a=3 FOR UPDATE;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
# Check that the above SELECT is blocked
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'statistics' and
|
||||||
|
info = 'SELECT b FROM t1 WHERE a=3 FOR UPDATE';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select4';
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
reap;
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
--error ER_DUP_ENTRY
|
||||||
|
reap;
|
||||||
|
SET DEBUG_SYNC='write_row_noreplace SIGNAL insert5 WAIT_FOR select5';
|
||||||
|
--send
|
||||||
|
LOAD DATA INFILE '../../std_data/loaddata5.dat' IGNORE INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b);
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert5';
|
||||||
|
SELECT * FROM t1;
|
||||||
|
# this should S-lock; no conflict
|
||||||
|
SELECT * FROM t1 WHERE a=3 LOCK IN SHARE MODE;
|
||||||
|
# this should X-lock, conflicting with the S-lock of the IGNORE in con1
|
||||||
|
--send
|
||||||
|
SELECT * FROM t1 WHERE a=3 FOR UPDATE;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
# Check that the above SELECT is blocked
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'statistics' and
|
||||||
|
info = 'SELECT * FROM t1 WHERE a=3 FOR UPDATE';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select5';
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
reap;
|
||||||
|
connection default;
|
||||||
|
reap;
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
SET DEBUG_SYNC='write_row_replace SIGNAL insert6 WAIT_FOR select6';
|
||||||
|
--send
|
||||||
|
LOAD DATA INFILE '../../std_data/loaddata5.dat' REPLACE INTO TABLE t1 FIELDS TERMINATED BY '' ENCLOSED BY '' (a, b);
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR insert6';
|
||||||
|
SELECT * FROM t1;
|
||||||
|
# this should conflict with the X-lock acquired by the REPLACE
|
||||||
|
--send
|
||||||
|
SELECT a,b FROM t1 LOCK IN SHARE MODE;
|
||||||
|
|
||||||
|
connection con2;
|
||||||
|
# Check that the above SELECT is blocked
|
||||||
|
let $wait_condition=
|
||||||
|
select count(*) = 1 from information_schema.processlist
|
||||||
|
where state = 'Sending data' and
|
||||||
|
info = 'SELECT a,b FROM t1 LOCK IN SHARE MODE';
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
SET DEBUG_SYNC='now SIGNAL select6';
|
||||||
|
|
||||||
|
connection con1;
|
||||||
|
reap;
|
||||||
|
connection default;
|
||||||
|
reap;
|
||||||
|
|
||||||
|
disconnect con1;
|
||||||
|
disconnect con2;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC='RESET';
|
||||||
|
DROP TABLE t1;
|
@ -1693,3 +1693,17 @@ INSERT INTO t1 SELECT t1.* FROM t1,t1 t2,t1 t3,t1 t4,t1 t5,t1 t6;
|
|||||||
SELECT * FROM t1 ORDER BY f LIMIT 1;
|
SELECT * FROM t1 ORDER BY f LIMIT 1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
SET sort_buffer_size=DEFAULT;
|
SET sort_buffer_size=DEFAULT;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # BUG#11758979 - 51252: ARCHIVE TABLES CAUSE 100% CPU USAGE
|
||||||
|
--echo # AND HANG IN SHOW TABLE STATUS
|
||||||
|
--echo # (to be executed with valgrind)
|
||||||
|
CREATE TABLE t1(a BLOB, b VARCHAR(200)) ENGINE=ARCHIVE;
|
||||||
|
INSERT INTO t1 VALUES(NULL, '');
|
||||||
|
FLUSH TABLE t1;
|
||||||
|
--echo # we need this select to workaround BUG#11764364
|
||||||
|
SELECT * FROM t1;
|
||||||
|
CHECKSUM TABLE t1 EXTENDED;
|
||||||
|
FLUSH TABLE t1;
|
||||||
|
OPTIMIZE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -12,4 +12,4 @@
|
|||||||
kill : Bug#11748945 2008-12-03 HHunger need some changes to be robust enough for pushbuild.
|
kill : Bug#11748945 2008-12-03 HHunger need some changes to be robust enough for pushbuild.
|
||||||
read_many_rows_innodb : Bug#11748886 2010-11-15 mattiasj report already exists
|
read_many_rows_innodb : Bug#11748886 2010-11-15 mattiasj report already exists
|
||||||
main.log_tables-big : Bug#11756699 2010-11-15 mattiasj report already exists
|
main.log_tables-big : Bug#11756699 2010-11-15 mattiasj report already exists
|
||||||
|
query_cache_28249 : Bug#12584161 2011-11-17 joh fails sporadically in 5.1 only
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
/*
|
/* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -12,8 +11,8 @@
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
*/
|
|
||||||
|
|
||||||
/* Workaround for Bug#32082: VOID redefinition on Win results in compile errors*/
|
/* Workaround for Bug#32082: VOID redefinition on Win results in compile errors*/
|
||||||
#define DONT_DEFINE_VOID 1
|
#define DONT_DEFINE_VOID 1
|
||||||
@ -57,10 +56,11 @@ void my_init_stacktrace()
|
|||||||
|
|
||||||
static void print_buffer(char *buffer, size_t count)
|
static void print_buffer(char *buffer, size_t count)
|
||||||
{
|
{
|
||||||
|
const char s[]= " ";
|
||||||
for (; count && *buffer; --count)
|
for (; count && *buffer; --count)
|
||||||
{
|
{
|
||||||
int c= (int) *buffer++;
|
my_write_stderr(isprint(*buffer) ? buffer : s, 1);
|
||||||
fputc(isprint(c) ? c : ' ', stderr);
|
++buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,10 +124,10 @@ static int safe_print_str(const char *addr, int max_len)
|
|||||||
|
|
||||||
/* Output a new line if something was printed. */
|
/* Output a new line if something was printed. */
|
||||||
if (total != (size_t) max_len)
|
if (total != (size_t) max_len)
|
||||||
fputc('\n', stderr);
|
my_safe_printf_stderr("%s", "\n");
|
||||||
|
|
||||||
if (nbytes == -1)
|
if (nbytes == -1)
|
||||||
fprintf(stderr, "Can't read from address %p: %m.\n", addr);
|
my_safe_printf_stderr("Can't read from address %p\n", addr);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
@ -149,13 +149,13 @@ void my_safe_print_str(const char* val, int max_len)
|
|||||||
|
|
||||||
if (!PTR_SANE(val))
|
if (!PTR_SANE(val))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "is an invalid pointer\n");
|
my_safe_printf_stderr("%s", "is an invalid pointer\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; max_len && PTR_SANE(val) && *val; --max_len)
|
for (; max_len && PTR_SANE(val) && *val; --max_len)
|
||||||
fputc(*val++, stderr);
|
my_write_stderr((val++), 1);
|
||||||
fputc('\n', stderr);
|
my_safe_printf_stderr("%s", "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_PRINTSTACK)
|
#if defined(HAVE_PRINTSTACK)
|
||||||
@ -167,14 +167,15 @@ void my_print_stacktrace(uchar* stack_bottom __attribute__((unused)),
|
|||||||
ulong thread_stack __attribute__((unused)))
|
ulong thread_stack __attribute__((unused)))
|
||||||
{
|
{
|
||||||
if (printstack(fileno(stderr)) == -1)
|
if (printstack(fileno(stderr)) == -1)
|
||||||
fprintf(stderr, "Error when traversing the stack, stack appears corrupt.\n");
|
my_safe_printf_stderr("%s",
|
||||||
|
"Error when traversing the stack, stack appears corrupt.\n");
|
||||||
else
|
else
|
||||||
fprintf(stderr,
|
my_safe_printf_stderr("%s"
|
||||||
"Please read "
|
"Please read "
|
||||||
"http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
|
"http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
|
||||||
"and follow instructions on how to resolve the stack trace.\n"
|
"and follow instructions on how to resolve the stack trace.\n"
|
||||||
"Resolved stack trace is much more helpful in diagnosing the\n"
|
"Resolved stack trace is much more helpful in diagnosing the\n"
|
||||||
"problem, so please do resolve it\n");
|
"problem, so please do resolve it\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD)
|
#elif HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD)
|
||||||
@ -212,9 +213,9 @@ static void my_demangle_symbols(char **addrs, int n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (demangled)
|
if (demangled)
|
||||||
fprintf(stderr, "%s(%s+%s\n", addrs[i], demangled, end);
|
my_safe_printf_stderr("%s(%s+%s\n", addrs[i], demangled, end);
|
||||||
else
|
else
|
||||||
fprintf(stderr, "%s\n", addrs[i]);
|
my_safe_printf_stderr("%s\n", addrs[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,8 +226,8 @@ void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
|
|||||||
void *addrs[128];
|
void *addrs[128];
|
||||||
char **strings= NULL;
|
char **strings= NULL;
|
||||||
int n = backtrace(addrs, array_elements(addrs));
|
int n = backtrace(addrs, array_elements(addrs));
|
||||||
fprintf(stderr, "stack_bottom = %p thread_stack 0x%lx\n",
|
my_safe_printf_stderr("stack_bottom = %p thread_stack 0x%lx\n",
|
||||||
stack_bottom, thread_stack);
|
stack_bottom, thread_stack);
|
||||||
#if BACKTRACE_DEMANGLE
|
#if BACKTRACE_DEMANGLE
|
||||||
if ((strings= backtrace_symbols(addrs, n)))
|
if ((strings= backtrace_symbols(addrs, n)))
|
||||||
{
|
{
|
||||||
@ -319,8 +320,9 @@ void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
|
|||||||
#endif
|
#endif
|
||||||
if (!fp)
|
if (!fp)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "frame pointer is NULL, did you compile with\n\
|
my_safe_printf_stderr("%s",
|
||||||
-fomit-frame-pointer? Aborting backtrace!\n");
|
"frame pointer is NULL, did you compile with\n"
|
||||||
|
"-fomit-frame-pointer? Aborting backtrace!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,24 +330,28 @@ void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
|
|||||||
{
|
{
|
||||||
ulong tmp= min(0x10000,thread_stack);
|
ulong tmp= min(0x10000,thread_stack);
|
||||||
/* Assume that the stack starts at the previous even 65K */
|
/* Assume that the stack starts at the previous even 65K */
|
||||||
stack_bottom= (uchar*) (((ulong) &fp + tmp) &
|
stack_bottom= (uchar*) (((ulong) &fp + tmp) & ~(ulong) 0xFFFF);
|
||||||
~(ulong) 0xFFFF);
|
my_safe_printf_stderr("Cannot determine thread, fp=%p, "
|
||||||
fprintf(stderr, "Cannot determine thread, fp=%p, backtrace may not be correct.\n", fp);
|
"backtrace may not be correct.\n", fp);
|
||||||
}
|
}
|
||||||
if (fp > (uchar**) stack_bottom ||
|
if (fp > (uchar**) stack_bottom ||
|
||||||
fp < (uchar**) stack_bottom - thread_stack)
|
fp < (uchar**) stack_bottom - thread_stack)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Bogus stack limit or frame pointer,\
|
my_safe_printf_stderr("Bogus stack limit or frame pointer, "
|
||||||
fp=%p, stack_bottom=%p, thread_stack=%ld, aborting backtrace.\n",
|
"fp=%p, stack_bottom=%p, thread_stack=%ld, "
|
||||||
fp, stack_bottom, thread_stack);
|
"aborting backtrace.\n",
|
||||||
|
fp, stack_bottom, thread_stack);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Stack range sanity check OK, backtrace follows:\n");
|
my_safe_printf_stderr("%s",
|
||||||
|
"Stack range sanity check OK, backtrace follows:\n");
|
||||||
#if defined(__alpha__) && defined(__GNUC__)
|
#if defined(__alpha__) && defined(__GNUC__)
|
||||||
fprintf(stderr, "Warning: Alpha stacks are difficult -\
|
my_safe_printf_stderr("%s",
|
||||||
will be taking some wild guesses, stack trace may be incorrect or \
|
"Warning: Alpha stacks are difficult -"
|
||||||
terminate abruptly\n");
|
"will be taking some wild guesses, stack trace may be incorrect or "
|
||||||
|
"terminate abruptly\n");
|
||||||
|
|
||||||
/* On Alpha, we need to get pc */
|
/* On Alpha, we need to get pc */
|
||||||
__asm __volatile__ ("bsr %0, do_next; do_next: "
|
__asm __volatile__ ("bsr %0, do_next; do_next: "
|
||||||
:"=r"(pc)
|
:"=r"(pc)
|
||||||
@ -359,8 +365,9 @@ void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
|
|||||||
{
|
{
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
uchar** new_fp = (uchar**)*fp;
|
uchar** new_fp = (uchar**)*fp;
|
||||||
fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ?
|
my_safe_printf_stderr("%p\n",
|
||||||
*(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
|
frame_count == sigreturn_frame_count ?
|
||||||
|
*(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1));
|
||||||
#endif /* defined(__386__) || defined(__x86_64__) */
|
#endif /* defined(__386__) || defined(__x86_64__) */
|
||||||
|
|
||||||
#if defined(__alpha__) && defined(__GNUC__)
|
#if defined(__alpha__) && defined(__GNUC__)
|
||||||
@ -374,38 +381,40 @@ void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack)
|
|||||||
{
|
{
|
||||||
pc = find_prev_pc(pc, fp);
|
pc = find_prev_pc(pc, fp);
|
||||||
if (pc)
|
if (pc)
|
||||||
fprintf(stderr, "%p\n", pc);
|
my_safe_printf_stderr("%p\n", pc);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Not smart enough to deal with the rest\
|
my_safe_printf_stderr("%s",
|
||||||
of this stack\n");
|
"Not smart enough to deal with the rest of this stack\n");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Not smart enough to deal with the rest of this stack\n");
|
my_safe_printf_stderr("%s",
|
||||||
|
"Not smart enough to deal with the rest of this stack\n");
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
#endif /* defined(__alpha__) && defined(__GNUC__) */
|
#endif /* defined(__alpha__) && defined(__GNUC__) */
|
||||||
if (new_fp <= fp )
|
if (new_fp <= fp )
|
||||||
{
|
{
|
||||||
fprintf(stderr, "New value of fp=%p failed sanity check,\
|
my_safe_printf_stderr("New value of fp=%p failed sanity check, "
|
||||||
terminating stack trace!\n", new_fp);
|
"terminating stack trace!\n", new_fp);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
fp = new_fp;
|
fp = new_fp;
|
||||||
++frame_count;
|
++frame_count;
|
||||||
}
|
}
|
||||||
|
my_safe_printf_stderr("%s",
|
||||||
fprintf(stderr, "Stack trace seems successful - bottom reached\n");
|
"Stack trace seems successful - bottom reached\n");
|
||||||
|
|
||||||
end:
|
end:
|
||||||
fprintf(stderr,
|
my_safe_printf_stderr("%s",
|
||||||
"Please read http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
|
"Please read "
|
||||||
"and follow instructions on how to resolve the stack trace.\n"
|
"http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n"
|
||||||
"Resolved stack trace is much more helpful in diagnosing the\n"
|
"and follow instructions on how to resolve the stack trace.\n"
|
||||||
"problem, so please do resolve it\n");
|
"Resolved stack trace is much more helpful in diagnosing the\n"
|
||||||
|
"problem, so please do resolve it\n");
|
||||||
}
|
}
|
||||||
#endif /* TARGET_OS_LINUX */
|
#endif /* TARGET_OS_LINUX */
|
||||||
#endif /* HAVE_STACKTRACE */
|
#endif /* HAVE_STACKTRACE */
|
||||||
@ -670,7 +679,7 @@ void my_print_stacktrace(uchar* unused1, ulong unused2)
|
|||||||
&(package.sym));
|
&(package.sym));
|
||||||
have_source= pSymGetLineFromAddr64(hProcess, addr, &line_offset, &line);
|
have_source= pSymGetLineFromAddr64(hProcess, addr, &line_offset, &line);
|
||||||
|
|
||||||
fprintf(stderr, "%p ", addr);
|
my_safe_printf_stderr("%p ", addr);
|
||||||
if(have_module)
|
if(have_module)
|
||||||
{
|
{
|
||||||
char *base_image_name= strrchr(module.ImageName, '\\');
|
char *base_image_name= strrchr(module.ImageName, '\\');
|
||||||
@ -678,12 +687,13 @@ void my_print_stacktrace(uchar* unused1, ulong unused2)
|
|||||||
base_image_name++;
|
base_image_name++;
|
||||||
else
|
else
|
||||||
base_image_name= module.ImageName;
|
base_image_name= module.ImageName;
|
||||||
fprintf(stderr, "%s!", base_image_name);
|
my_safe_printf_stderr("%s!", base_image_name);
|
||||||
}
|
}
|
||||||
if(have_symbol)
|
if(have_symbol)
|
||||||
fprintf(stderr, "%s()", package.sym.Name);
|
my_safe_printf_stderr("%s()", package.sym.Name);
|
||||||
|
|
||||||
else if(have_module)
|
else if(have_module)
|
||||||
fprintf(stderr, "???");
|
my_safe_printf_stderr("%s", "???");
|
||||||
|
|
||||||
if(have_source)
|
if(have_source)
|
||||||
{
|
{
|
||||||
@ -692,11 +702,11 @@ void my_print_stacktrace(uchar* unused1, ulong unused2)
|
|||||||
base_file_name++;
|
base_file_name++;
|
||||||
else
|
else
|
||||||
base_file_name= line.FileName;
|
base_file_name= line.FileName;
|
||||||
fprintf(stderr,"[%s:%u]", base_file_name, line.LineNumber);
|
my_safe_printf_stderr("[%s:%u]",
|
||||||
|
base_file_name, line.LineNumber);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "\n");
|
my_safe_printf_stderr("%s", "\n");
|
||||||
}
|
}
|
||||||
fflush(stderr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -733,22 +743,22 @@ void my_write_core(int unused)
|
|||||||
if(pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
|
if(pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
|
||||||
hFile, MiniDumpNormal, &info, 0, 0))
|
hFile, MiniDumpNormal, &info, 0, 0))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Minidump written to %s\n",
|
my_safe_printf_stderr("Minidump written to %s\n",
|
||||||
_fullpath(path, dump_fname, sizeof(path)) ? path : dump_fname);
|
_fullpath(path, dump_fname, sizeof(path)) ?
|
||||||
|
path : dump_fname);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr,"MiniDumpWriteDump() failed, last error %u\n",
|
my_safe_printf_stderr("MiniDumpWriteDump() failed, last error %u\n",
|
||||||
GetLastError());
|
(uint) GetLastError());
|
||||||
}
|
}
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "CreateFile(%s) failed, last error %u\n", dump_fname,
|
my_safe_printf_stderr("CreateFile(%s) failed, last error %u\n",
|
||||||
GetLastError());
|
dump_fname, (uint) GetLastError());
|
||||||
}
|
}
|
||||||
fflush(stderr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -756,11 +766,212 @@ void my_safe_print_str(const char *val, int len)
|
|||||||
{
|
{
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
fprintf(stderr,"=%.*s\n", len, val);
|
my_write_stderr(val, len);
|
||||||
}
|
}
|
||||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
fprintf(stderr,"is an invalid string pointer\n");
|
my_safe_printf_stderr("%s", "is an invalid string pointer\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /*__WIN__*/
|
#endif /*__WIN__*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __WIN__
|
||||||
|
size_t my_write_stderr(const void *buf, size_t count)
|
||||||
|
{
|
||||||
|
DWORD bytes_written;
|
||||||
|
SetFilePointer(GetStdHandle(STD_ERROR_HANDLE), 0, NULL, FILE_END);
|
||||||
|
WriteFile(GetStdHandle(STD_ERROR_HANDLE), buf, count, &bytes_written, NULL);
|
||||||
|
return bytes_written;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
size_t my_write_stderr(const void *buf, size_t count)
|
||||||
|
{
|
||||||
|
return (size_t) write(STDERR_FILENO, buf, count);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static const char digits[]= "0123456789abcdef";
|
||||||
|
|
||||||
|
char *my_safe_utoa(int base, ulonglong val, char *buf)
|
||||||
|
{
|
||||||
|
*buf--= 0;
|
||||||
|
do {
|
||||||
|
*buf--= digits[val % base];
|
||||||
|
} while ((val /= base) != 0);
|
||||||
|
return buf + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *my_safe_itoa(int base, longlong val, char *buf)
|
||||||
|
{
|
||||||
|
char *orig_buf= buf;
|
||||||
|
const my_bool is_neg= (val < 0);
|
||||||
|
*buf--= 0;
|
||||||
|
|
||||||
|
if (is_neg)
|
||||||
|
val= -val;
|
||||||
|
if (is_neg && base == 16)
|
||||||
|
{
|
||||||
|
int ix;
|
||||||
|
val-= 1;
|
||||||
|
for (ix= 0; ix < 16; ++ix)
|
||||||
|
buf[-ix]= '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
*buf--= digits[val % base];
|
||||||
|
} while ((val /= base) != 0);
|
||||||
|
|
||||||
|
if (is_neg && base == 10)
|
||||||
|
*buf--= '-';
|
||||||
|
|
||||||
|
if (is_neg && base == 16)
|
||||||
|
{
|
||||||
|
int ix;
|
||||||
|
buf= orig_buf - 1;
|
||||||
|
for (ix= 0; ix < 16; ++ix, --buf)
|
||||||
|
{
|
||||||
|
switch (*buf)
|
||||||
|
{
|
||||||
|
case '0': *buf= 'f'; break;
|
||||||
|
case '1': *buf= 'e'; break;
|
||||||
|
case '2': *buf= 'd'; break;
|
||||||
|
case '3': *buf= 'c'; break;
|
||||||
|
case '4': *buf= 'b'; break;
|
||||||
|
case '5': *buf= 'a'; break;
|
||||||
|
case '6': *buf= '9'; break;
|
||||||
|
case '7': *buf= '8'; break;
|
||||||
|
case '8': *buf= '7'; break;
|
||||||
|
case '9': *buf= '6'; break;
|
||||||
|
case 'a': *buf= '5'; break;
|
||||||
|
case 'b': *buf= '4'; break;
|
||||||
|
case 'c': *buf= '3'; break;
|
||||||
|
case 'd': *buf= '2'; break;
|
||||||
|
case 'e': *buf= '1'; break;
|
||||||
|
case 'f': *buf= '0'; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char *check_longlong(const char *fmt, my_bool *have_longlong)
|
||||||
|
{
|
||||||
|
*have_longlong= FALSE;
|
||||||
|
if (*fmt == 'l')
|
||||||
|
{
|
||||||
|
fmt++;
|
||||||
|
if (*fmt != 'l')
|
||||||
|
*have_longlong= (sizeof(long) == sizeof(longlong));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fmt++;
|
||||||
|
*have_longlong= TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t my_safe_vsnprintf(char *to, size_t size,
|
||||||
|
const char* format, va_list ap)
|
||||||
|
{
|
||||||
|
char *start= to;
|
||||||
|
char *end= start + size - 1;
|
||||||
|
for (; *format; ++format)
|
||||||
|
{
|
||||||
|
my_bool have_longlong = FALSE;
|
||||||
|
if (*format != '%')
|
||||||
|
{
|
||||||
|
if (to == end) /* end of buffer */
|
||||||
|
break;
|
||||||
|
*to++= *format; /* copy ordinary char */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++format; /* skip '%' */
|
||||||
|
|
||||||
|
format= check_longlong(format, &have_longlong);
|
||||||
|
|
||||||
|
switch (*format)
|
||||||
|
{
|
||||||
|
case 'd':
|
||||||
|
case 'i':
|
||||||
|
case 'u':
|
||||||
|
case 'x':
|
||||||
|
case 'p':
|
||||||
|
{
|
||||||
|
longlong ival= 0;
|
||||||
|
ulonglong uval = 0;
|
||||||
|
if (*format == 'p')
|
||||||
|
have_longlong= (sizeof(void *) == sizeof(longlong));
|
||||||
|
if (have_longlong)
|
||||||
|
{
|
||||||
|
if (*format == 'u')
|
||||||
|
uval= va_arg(ap, ulonglong);
|
||||||
|
else
|
||||||
|
ival= va_arg(ap, longlong);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*format == 'u')
|
||||||
|
uval= va_arg(ap, unsigned int);
|
||||||
|
else
|
||||||
|
ival= va_arg(ap, int);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char buff[22];
|
||||||
|
const int base= (*format == 'x' || *format == 'p') ? 16 : 10;
|
||||||
|
char *val_as_str= (*format == 'u') ?
|
||||||
|
my_safe_utoa(base, uval, &buff[sizeof(buff)-1]) :
|
||||||
|
my_safe_itoa(base, ival, &buff[sizeof(buff)-1]);
|
||||||
|
|
||||||
|
/* Strip off "ffffffff" if we have 'x' format without 'll' */
|
||||||
|
if (*format == 'x' && !have_longlong && ival < 0)
|
||||||
|
val_as_str+= 8;
|
||||||
|
|
||||||
|
while (*val_as_str && to < end)
|
||||||
|
*to++= *val_as_str++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 's':
|
||||||
|
{
|
||||||
|
const char *val= va_arg(ap, char*);
|
||||||
|
if (!val)
|
||||||
|
val= "(null)";
|
||||||
|
while (*val && to < end)
|
||||||
|
*to++= *val++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*to= 0;
|
||||||
|
return to - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t my_safe_snprintf(char* to, size_t n, const char* fmt, ...)
|
||||||
|
{
|
||||||
|
size_t result;
|
||||||
|
va_list args;
|
||||||
|
va_start(args,fmt);
|
||||||
|
result= my_safe_vsnprintf(to, n, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t my_safe_printf_stderr(const char* fmt, ...)
|
||||||
|
{
|
||||||
|
char to[512];
|
||||||
|
size_t result;
|
||||||
|
va_list args;
|
||||||
|
va_start(args,fmt);
|
||||||
|
result= my_safe_vsnprintf(to, sizeof(to), fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
my_write_stderr(to, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -65,6 +65,7 @@ SET (SQL_SOURCE
|
|||||||
sql_list.cc sql_load.cc sql_manager.cc sql_map.cc sql_parse.cc
|
sql_list.cc sql_load.cc sql_manager.cc sql_map.cc sql_parse.cc
|
||||||
sql_partition.cc sql_plugin.cc sql_prepare.cc sql_rename.cc
|
sql_partition.cc sql_plugin.cc sql_prepare.cc sql_rename.cc
|
||||||
debug_sync.cc debug_sync.h
|
debug_sync.cc debug_sync.h
|
||||||
|
signal_handler.cc
|
||||||
sql_repl.cc sql_select.cc sql_show.cc sql_state.c sql_string.cc
|
sql_repl.cc sql_select.cc sql_show.cc sql_state.c sql_string.cc
|
||||||
sql_table.cc sql_test.cc sql_trigger.cc sql_udf.cc sql_union.cc
|
sql_table.cc sql_test.cc sql_trigger.cc sql_udf.cc sql_union.cc
|
||||||
sql_update.cc sql_view.cc strfunc.cc table.cc thr_malloc.cc
|
sql_update.cc sql_view.cc strfunc.cc table.cc thr_malloc.cc
|
||||||
@ -113,7 +114,7 @@ IF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS)
|
|||||||
ADD_CUSTOM_COMMAND(TARGET mysqld PRE_LINK
|
ADD_CUSTOM_COMMAND(TARGET mysqld PRE_LINK
|
||||||
COMMAND cscript ARGS //nologo ${PROJECT_SOURCE_DIR}/win/create_def_file.js
|
COMMAND cscript ARGS //nologo ${PROJECT_SOURCE_DIR}/win/create_def_file.js
|
||||||
${PLATFORM} ${LIB_LOCATIONS} > mysqld.def
|
${PLATFORM} ${LIB_LOCATIONS} > mysqld.def
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/sql)
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
ENDIF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS)
|
ENDIF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS)
|
||||||
|
|
||||||
ADD_DEPENDENCIES(sql GenError)
|
ADD_DEPENDENCIES(sql GenError)
|
||||||
|
@ -103,6 +103,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
|
|||||||
records.cc filesort.cc handler.cc \
|
records.cc filesort.cc handler.cc \
|
||||||
ha_partition.cc \
|
ha_partition.cc \
|
||||||
debug_sync.cc \
|
debug_sync.cc \
|
||||||
|
signal_handler.cc \
|
||||||
sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc \
|
sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc \
|
||||||
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
|
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
|
||||||
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
|
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
|
||||||
|
17
sql/field.h
17
sql/field.h
@ -2128,6 +2128,23 @@ public:
|
|||||||
uchar *from_null_ptr,*to_null_ptr;
|
uchar *from_null_ptr,*to_null_ptr;
|
||||||
my_bool *null_row;
|
my_bool *null_row;
|
||||||
uint from_bit,to_bit;
|
uint from_bit,to_bit;
|
||||||
|
/**
|
||||||
|
Number of bytes in the fields pointed to by 'from_ptr' and
|
||||||
|
'to_ptr'. Usually this is the number of bytes that are copied from
|
||||||
|
'from_ptr' to 'to_ptr'.
|
||||||
|
|
||||||
|
For variable-length fields (VARCHAR), the first byte(s) describe
|
||||||
|
the actual length of the text. For VARCHARs with length
|
||||||
|
< 256 there is 1 length byte
|
||||||
|
>= 256 there is 2 length bytes
|
||||||
|
Thus, if from_field is VARCHAR(10), from_length (and in most cases
|
||||||
|
to_length) is 11. For VARCHAR(1024), the length is 1026. @see
|
||||||
|
Field_varstring::length_bytes
|
||||||
|
|
||||||
|
Note that for VARCHARs, do_copy() will be do_varstring*() which
|
||||||
|
only copies the length-bytes (1 or 2) + the actual length of the
|
||||||
|
text instead of from/to_length bytes. @see get_copy_func()
|
||||||
|
*/
|
||||||
uint from_length,to_length;
|
uint from_length,to_length;
|
||||||
Field *from_field,*to_field;
|
Field *from_field,*to_field;
|
||||||
String tmp; // For items
|
String tmp; // For items
|
||||||
|
@ -707,7 +707,7 @@ Copy_field::get_copy_func(Field *to,Field *from)
|
|||||||
if (((Field_varstring*) to)->length_bytes !=
|
if (((Field_varstring*) to)->length_bytes !=
|
||||||
((Field_varstring*) from)->length_bytes)
|
((Field_varstring*) from)->length_bytes)
|
||||||
return do_field_string;
|
return do_field_string;
|
||||||
if (to_length != from_length)
|
else
|
||||||
return (((Field_varstring*) to)->length_bytes == 1 ?
|
return (((Field_varstring*) to)->length_bytes == 1 ?
|
||||||
(from->charset()->mbmaxlen == 1 ? do_varstring1 :
|
(from->charset()->mbmaxlen == 1 ? do_varstring1 :
|
||||||
do_varstring1_mb) :
|
do_varstring1_mb) :
|
||||||
|
@ -1854,7 +1854,7 @@ static void setup_windows_event_source()
|
|||||||
|
|
||||||
static int find_uniq_filename(char *name)
|
static int find_uniq_filename(char *name)
|
||||||
{
|
{
|
||||||
long number;
|
long number= 0;
|
||||||
uint i;
|
uint i;
|
||||||
char buff[FN_REFLEN];
|
char buff[FN_REFLEN];
|
||||||
struct st_my_dir *dir_info;
|
struct st_my_dir *dir_info;
|
||||||
|
186
sql/mysqld.cc
186
sql/mysqld.cc
@ -124,9 +124,6 @@ extern "C" { // Because of SCO 3.2V4.2
|
|||||||
|
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
#include <crtdbg.h>
|
#include <crtdbg.h>
|
||||||
#define SIGNAL_FMT "exception 0x%x"
|
|
||||||
#else
|
|
||||||
#define SIGNAL_FMT "signal %d"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __NETWARE__
|
#ifdef __NETWARE__
|
||||||
@ -269,7 +266,7 @@ inline void setup_fpu()
|
|||||||
extern "C" int gethostname(char *name, int namelen);
|
extern "C" int gethostname(char *name, int namelen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern "C" sig_handler handle_segfault(int sig);
|
extern "C" sig_handler handle_fatal_signal(int sig);
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
#define ENABLE_TEMP_POOL 1
|
#define ENABLE_TEMP_POOL 1
|
||||||
@ -415,6 +412,10 @@ TYPELIB log_output_typelib= {array_elements(log_output_names)-1,"",
|
|||||||
|
|
||||||
/* static variables */
|
/* static variables */
|
||||||
|
|
||||||
|
#ifdef HAVE_NPTL
|
||||||
|
volatile sig_atomic_t ld_assume_kernel_is_set= 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* the default log output is log tables */
|
/* the default log output is log tables */
|
||||||
static bool lower_case_table_names_used= 0;
|
static bool lower_case_table_names_used= 0;
|
||||||
static bool max_long_data_size_used= false;
|
static bool max_long_data_size_used= false;
|
||||||
@ -424,7 +425,7 @@ static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
|
|||||||
static my_bool opt_short_log_format= 0;
|
static my_bool opt_short_log_format= 0;
|
||||||
static uint kill_cached_threads, wake_thread;
|
static uint kill_cached_threads, wake_thread;
|
||||||
static ulong killed_threads, thread_created;
|
static ulong killed_threads, thread_created;
|
||||||
static ulong max_used_connections;
|
ulong max_used_connections;
|
||||||
static ulong my_bind_addr; /**< the address we bind to */
|
static ulong my_bind_addr; /**< the address we bind to */
|
||||||
static volatile ulong cached_thread_count= 0;
|
static volatile ulong cached_thread_count= 0;
|
||||||
static const char *sql_mode_str= "OFF";
|
static const char *sql_mode_str= "OFF";
|
||||||
@ -553,7 +554,7 @@ TYPELIB binlog_format_typelib=
|
|||||||
ulong opt_binlog_format_id= (ulong) BINLOG_FORMAT_UNSPEC;
|
ulong opt_binlog_format_id= (ulong) BINLOG_FORMAT_UNSPEC;
|
||||||
const char *opt_binlog_format= binlog_format_names[opt_binlog_format_id];
|
const char *opt_binlog_format= binlog_format_names[opt_binlog_format_id];
|
||||||
#ifdef HAVE_INITGROUPS
|
#ifdef HAVE_INITGROUPS
|
||||||
static bool calling_initgroups= FALSE; /**< Used in SIGSEGV handler. */
|
volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */
|
||||||
#endif
|
#endif
|
||||||
uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
|
uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
|
||||||
uint mysqld_port_timeout;
|
uint mysqld_port_timeout;
|
||||||
@ -727,7 +728,7 @@ char *opt_logname, *opt_slow_logname;
|
|||||||
|
|
||||||
/* Static variables */
|
/* Static variables */
|
||||||
|
|
||||||
static bool kill_in_progress, segfaulted;
|
static volatile sig_atomic_t kill_in_progress;
|
||||||
#ifdef HAVE_STACK_TRACE_ON_SEGV
|
#ifdef HAVE_STACK_TRACE_ON_SEGV
|
||||||
static my_bool opt_do_pstack;
|
static my_bool opt_do_pstack;
|
||||||
#endif /* HAVE_STACK_TRACE_ON_SEGV */
|
#endif /* HAVE_STACK_TRACE_ON_SEGV */
|
||||||
@ -1616,9 +1617,9 @@ static void set_user(const char *user, struct passwd *user_info_arg)
|
|||||||
calling_initgroups as a flag to the SIGSEGV handler that is then used to
|
calling_initgroups as a flag to the SIGSEGV handler that is then used to
|
||||||
output a specific message to help the user resolve this problem.
|
output a specific message to help the user resolve this problem.
|
||||||
*/
|
*/
|
||||||
calling_initgroups= TRUE;
|
calling_initgroups= 1;
|
||||||
initgroups((char*) user, user_info_arg->pw_gid);
|
initgroups((char*) user, user_info_arg->pw_gid);
|
||||||
calling_initgroups= FALSE;
|
calling_initgroups= 0;
|
||||||
#endif
|
#endif
|
||||||
if (setgid(user_info_arg->pw_gid) == -1)
|
if (setgid(user_info_arg->pw_gid) == -1)
|
||||||
{
|
{
|
||||||
@ -2170,7 +2171,7 @@ LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers)
|
|||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
my_set_exception_pointers(ex_pointers);
|
my_set_exception_pointers(ex_pointers);
|
||||||
handle_segfault(ex_pointers->ExceptionRecord->ExceptionCode);
|
handle_fatal_signal(ex_pointers->ExceptionRecord->ExceptionCode);
|
||||||
}
|
}
|
||||||
__except(EXCEPTION_EXECUTE_HANDLER)
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
@ -2481,161 +2482,6 @@ extern "C" char *my_demangle(const char *mangled_name, int *status)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
extern "C" sig_handler handle_segfault(int sig)
|
|
||||||
{
|
|
||||||
time_t curr_time;
|
|
||||||
struct tm tm;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Strictly speaking, one needs a mutex here
|
|
||||||
but since we have got SIGSEGV already, things are a mess
|
|
||||||
so not having the mutex is not as bad as possibly using a buggy
|
|
||||||
mutex - so we keep things simple
|
|
||||||
*/
|
|
||||||
if (segfaulted)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Fatal " SIGNAL_FMT " while backtracing\n", sig);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
segfaulted = 1;
|
|
||||||
|
|
||||||
curr_time= my_time(0);
|
|
||||||
localtime_r(&curr_time, &tm);
|
|
||||||
|
|
||||||
fprintf(stderr,"\
|
|
||||||
%02d%02d%02d %2d:%02d:%02d - mysqld got " SIGNAL_FMT " ;\n\
|
|
||||||
This could be because you hit a bug. It is also possible that this binary\n\
|
|
||||||
or one of the libraries it was linked against is corrupt, improperly built,\n\
|
|
||||||
or misconfigured. This error can also be caused by malfunctioning hardware.\n",
|
|
||||||
tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
|
|
||||||
tm.tm_hour, tm.tm_min, tm.tm_sec,
|
|
||||||
sig);
|
|
||||||
fprintf(stderr, "\
|
|
||||||
We will try our best to scrape up some info that will hopefully help diagnose\n\
|
|
||||||
the problem, but since we have already crashed, something is definitely wrong\n\
|
|
||||||
and this may fail.\n\n");
|
|
||||||
fprintf(stderr, "key_buffer_size=%lu\n",
|
|
||||||
(ulong) dflt_key_cache->key_cache_mem_size);
|
|
||||||
fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size);
|
|
||||||
fprintf(stderr, "max_used_connections=%lu\n", max_used_connections);
|
|
||||||
fprintf(stderr, "max_threads=%u\n", thread_scheduler.max_threads);
|
|
||||||
fprintf(stderr, "threads_connected=%u\n", thread_count);
|
|
||||||
fprintf(stderr, "It is possible that mysqld could use up to \n\
|
|
||||||
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = %lu K\n\
|
|
||||||
bytes of memory\n", ((ulong) dflt_key_cache->key_cache_mem_size +
|
|
||||||
(global_system_variables.read_buff_size +
|
|
||||||
global_system_variables.sortbuff_size) *
|
|
||||||
thread_scheduler.max_threads +
|
|
||||||
max_connections * sizeof(THD)) / 1024);
|
|
||||||
fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
|
|
||||||
|
|
||||||
#if defined(HAVE_LINUXTHREADS)
|
|
||||||
if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "\
|
|
||||||
You seem to be running 32-bit Linux and have %d concurrent connections.\n\
|
|
||||||
If you have not changed STACK_SIZE in LinuxThreads and built the binary \n\
|
|
||||||
yourself, LinuxThreads is quite likely to steal a part of the global heap for\n\
|
|
||||||
the thread stack. Please read http://dev.mysql.com/doc/mysql/en/linux.html\n\n",
|
|
||||||
thread_count);
|
|
||||||
}
|
|
||||||
#endif /* HAVE_LINUXTHREADS */
|
|
||||||
|
|
||||||
#ifdef HAVE_STACKTRACE
|
|
||||||
THD *thd=current_thd;
|
|
||||||
|
|
||||||
if (!(test_flags & TEST_NO_STACKTRACE))
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Thread pointer: 0x%lx\n", (long) thd);
|
|
||||||
fprintf(stderr, "Attempting backtrace. You can use the following "
|
|
||||||
"information to find out\nwhere mysqld died. If "
|
|
||||||
"you see no messages after this, something went\n"
|
|
||||||
"terribly wrong...\n");
|
|
||||||
my_print_stacktrace(thd ? (uchar*) thd->thread_stack : NULL,
|
|
||||||
my_thread_stack_size);
|
|
||||||
}
|
|
||||||
if (thd)
|
|
||||||
{
|
|
||||||
const char *kreason= "UNKNOWN";
|
|
||||||
switch (thd->killed) {
|
|
||||||
case THD::NOT_KILLED:
|
|
||||||
kreason= "NOT_KILLED";
|
|
||||||
break;
|
|
||||||
case THD::KILL_BAD_DATA:
|
|
||||||
kreason= "KILL_BAD_DATA";
|
|
||||||
break;
|
|
||||||
case THD::KILL_CONNECTION:
|
|
||||||
kreason= "KILL_CONNECTION";
|
|
||||||
break;
|
|
||||||
case THD::KILL_QUERY:
|
|
||||||
kreason= "KILL_QUERY";
|
|
||||||
break;
|
|
||||||
case THD::KILLED_NO_VALUE:
|
|
||||||
kreason= "KILLED_NO_VALUE";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fprintf(stderr, "\nTrying to get some variables.\n"
|
|
||||||
"Some pointers may be invalid and cause the dump to abort.\n");
|
|
||||||
fprintf(stderr, "Query (%p): ", thd->query());
|
|
||||||
my_safe_print_str(thd->query(), min(1024, thd->query_length()));
|
|
||||||
fprintf(stderr, "Connection ID (thread ID): %lu\n", (ulong) thd->thread_id);
|
|
||||||
fprintf(stderr, "Status: %s\n", kreason);
|
|
||||||
fputc('\n', stderr);
|
|
||||||
}
|
|
||||||
fprintf(stderr, "\
|
|
||||||
The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains\n\
|
|
||||||
information that should help you find out what is causing the crash.\n");
|
|
||||||
fflush(stderr);
|
|
||||||
#endif /* HAVE_STACKTRACE */
|
|
||||||
|
|
||||||
#ifdef HAVE_INITGROUPS
|
|
||||||
if (calling_initgroups)
|
|
||||||
fprintf(stderr, "\n\
|
|
||||||
This crash occured while the server was calling initgroups(). This is\n\
|
|
||||||
often due to the use of a mysqld that is statically linked against glibc\n\
|
|
||||||
and configured to use LDAP in /etc/nsswitch.conf. You will need to either\n\
|
|
||||||
upgrade to a version of glibc that does not have this problem (2.3.4 or\n\
|
|
||||||
later when used with nscd), disable LDAP in your nsswitch.conf, or use a\n\
|
|
||||||
mysqld that is not statically linked.\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_NPTL
|
|
||||||
if (thd_lib_detected == THD_LIB_LT && !getenv("LD_ASSUME_KERNEL"))
|
|
||||||
fprintf(stderr,"\n\
|
|
||||||
You are running a statically-linked LinuxThreads binary on an NPTL system.\n\
|
|
||||||
This can result in crashes on some distributions due to LT/NPTL conflicts.\n\
|
|
||||||
You should either build a dynamically-linked binary, or force LinuxThreads\n\
|
|
||||||
to be used with the LD_ASSUME_KERNEL environment variable. Please consult\n\
|
|
||||||
the documentation for your distribution on how to do that.\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (locked_in_memory)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "\n\
|
|
||||||
The \"--memlock\" argument, which was enabled, uses system calls that are\n\
|
|
||||||
unreliable and unstable on some operating systems and operating-system\n\
|
|
||||||
versions (notably, some versions of Linux). This crash could be due to use\n\
|
|
||||||
of those buggy OS calls. You should consider whether you really need the\n\
|
|
||||||
\"--memlock\" parameter and/or consult the OS distributer about \"mlockall\"\n\
|
|
||||||
bugs.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_WRITE_CORE
|
|
||||||
if (test_flags & TEST_CORE_ON_SIGNAL)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Writing a core file\n");
|
|
||||||
fflush(stderr);
|
|
||||||
my_write_core(sig);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __WIN__
|
|
||||||
/* On Windows, do not terminate, but pass control to exception filter */
|
|
||||||
exit(1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(__WIN__) && !defined(__NETWARE__)
|
#if !defined(__WIN__) && !defined(__NETWARE__)
|
||||||
#ifndef SA_RESETHAND
|
#ifndef SA_RESETHAND
|
||||||
#define SA_RESETHAND 0
|
#define SA_RESETHAND 0
|
||||||
@ -2664,9 +2510,9 @@ static void init_signals(void)
|
|||||||
my_init_stacktrace();
|
my_init_stacktrace();
|
||||||
#endif
|
#endif
|
||||||
#if defined(__amiga__)
|
#if defined(__amiga__)
|
||||||
sa.sa_handler=(void(*)())handle_segfault;
|
sa.sa_handler=(void(*)())handle_fatal_signal;
|
||||||
#else
|
#else
|
||||||
sa.sa_handler=handle_segfault;
|
sa.sa_handler=handle_fatal_signal;
|
||||||
#endif
|
#endif
|
||||||
sigaction(SIGSEGV, &sa, NULL);
|
sigaction(SIGSEGV, &sa, NULL);
|
||||||
sigaction(SIGABRT, &sa, NULL);
|
sigaction(SIGABRT, &sa, NULL);
|
||||||
@ -4363,6 +4209,10 @@ int win_main(int argc, char **argv)
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_NPTL
|
||||||
|
ld_assume_kernel_is_set= (getenv("LD_ASSUME_KERNEL") != 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
MY_INIT(argv[0]); // init my_sys library & pthreads
|
MY_INIT(argv[0]); // init my_sys library & pthreads
|
||||||
/* nothing should come before this line ^^^ */
|
/* nothing should come before this line ^^^ */
|
||||||
|
|
||||||
@ -7876,7 +7726,7 @@ static int mysql_init_variables(void)
|
|||||||
opt_secure_file_priv= 0;
|
opt_secure_file_priv= 0;
|
||||||
opt_bootstrap= opt_myisam_log= 0;
|
opt_bootstrap= opt_myisam_log= 0;
|
||||||
mqh_used= 0;
|
mqh_used= 0;
|
||||||
segfaulted= kill_in_progress= 0;
|
kill_in_progress= 0;
|
||||||
cleanup_done= 0;
|
cleanup_done= 0;
|
||||||
defaults_argc= 0;
|
defaults_argc= 0;
|
||||||
defaults_argv= 0;
|
defaults_argv= 0;
|
||||||
|
257
sql/signal_handler.cc
Normal file
257
sql/signal_handler.cc
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 of the License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
#include "my_global.h"
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#include "mysql_priv.h"
|
||||||
|
#include "my_stacktrace.h"
|
||||||
|
|
||||||
|
#ifdef __WIN__
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#define SIGNAL_FMT "exception 0x%x"
|
||||||
|
#else
|
||||||
|
#define SIGNAL_FMT "signal %d"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
We are handling signals in this file.
|
||||||
|
Any global variables we read should be 'volatile sig_atomic_t'
|
||||||
|
to guarantee that we read some consistent value.
|
||||||
|
*/
|
||||||
|
static volatile sig_atomic_t segfaulted= 0;
|
||||||
|
extern ulong max_used_connections;
|
||||||
|
extern volatile sig_atomic_t calling_initgroups;
|
||||||
|
#ifdef HAVE_NPTL
|
||||||
|
extern volatile sig_atomic_t ld_assume_kernel_is_set;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for fatal signals
|
||||||
|
*
|
||||||
|
* Fatal events (seg.fault, bus error etc.) will trigger
|
||||||
|
* this signal handler. The handler will try to dump relevant
|
||||||
|
* debugging information to stderr and dump a core image.
|
||||||
|
*
|
||||||
|
* Signal handlers can only use a set of 'safe' system calls
|
||||||
|
* and library functions. A list of safe calls in POSIX systems
|
||||||
|
* are available at:
|
||||||
|
* http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html
|
||||||
|
* For MS Windows, guidelines are available at:
|
||||||
|
* http://msdn.microsoft.com/en-us/library/xdkz3x12(v=vs.71).aspx
|
||||||
|
*
|
||||||
|
* @param sig Signal number
|
||||||
|
*/
|
||||||
|
extern "C" sig_handler handle_fatal_signal(int sig)
|
||||||
|
{
|
||||||
|
if (segfaulted)
|
||||||
|
{
|
||||||
|
my_safe_printf_stderr("Fatal " SIGNAL_FMT " while backtracing\n", sig);
|
||||||
|
_exit(1); /* Quit without running destructors */
|
||||||
|
}
|
||||||
|
|
||||||
|
segfaulted = 1;
|
||||||
|
|
||||||
|
#ifdef __WIN__
|
||||||
|
SYSTEMTIME utc_time;
|
||||||
|
GetSystemTime(&utc_time);
|
||||||
|
const long hrs= utc_time.wHour;
|
||||||
|
const long mins= utc_time.wMinute;
|
||||||
|
const long secs= utc_time.wSecond;
|
||||||
|
#else
|
||||||
|
/* Using time() instead of my_time() to avoid looping */
|
||||||
|
const time_t curr_time= time(NULL);
|
||||||
|
/* Calculate time of day */
|
||||||
|
const long tmins = curr_time / 60;
|
||||||
|
const long thrs = tmins / 60;
|
||||||
|
const long hrs = thrs % 24;
|
||||||
|
const long mins = tmins % 60;
|
||||||
|
const long secs = curr_time % 60;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char hrs_buf[3]= "00";
|
||||||
|
char mins_buf[3]= "00";
|
||||||
|
char secs_buf[3]= "00";
|
||||||
|
my_safe_itoa(10, hrs, &hrs_buf[2]);
|
||||||
|
my_safe_itoa(10, mins, &mins_buf[2]);
|
||||||
|
my_safe_itoa(10, secs, &secs_buf[2]);
|
||||||
|
|
||||||
|
my_safe_printf_stderr("%s:%s:%s UTC - mysqld got " SIGNAL_FMT " ;\n",
|
||||||
|
hrs_buf, mins_buf, secs_buf, sig);
|
||||||
|
|
||||||
|
my_safe_printf_stderr("%s",
|
||||||
|
"This could be because you hit a bug. It is also possible that this binary\n"
|
||||||
|
"or one of the libraries it was linked against is corrupt, improperly built,\n"
|
||||||
|
"or misconfigured. This error can also be caused by malfunctioning hardware.\n");
|
||||||
|
|
||||||
|
my_safe_printf_stderr("%s",
|
||||||
|
"We will try our best to scrape up some info that will hopefully help\n"
|
||||||
|
"diagnose the problem, but since we have already crashed, \n"
|
||||||
|
"something is definitely wrong and this may fail.\n\n");
|
||||||
|
|
||||||
|
my_safe_printf_stderr("key_buffer_size=%lu\n",
|
||||||
|
(ulong) dflt_key_cache->key_cache_mem_size);
|
||||||
|
|
||||||
|
my_safe_printf_stderr("read_buffer_size=%ld\n",
|
||||||
|
(long) global_system_variables.read_buff_size);
|
||||||
|
|
||||||
|
my_safe_printf_stderr("max_used_connections=%lu\n",
|
||||||
|
(ulong) max_used_connections);
|
||||||
|
|
||||||
|
my_safe_printf_stderr("max_threads=%u\n",
|
||||||
|
(uint) thread_scheduler.max_threads);
|
||||||
|
|
||||||
|
my_safe_printf_stderr("thread_count=%u\n", (uint) thread_count);
|
||||||
|
|
||||||
|
my_safe_printf_stderr("connection_count=%u\n", (uint) connection_count);
|
||||||
|
|
||||||
|
my_safe_printf_stderr("It is possible that mysqld could use up to \n"
|
||||||
|
"key_buffer_size + "
|
||||||
|
"(read_buffer_size + sort_buffer_size)*max_threads = "
|
||||||
|
"%lu K bytes of memory\n",
|
||||||
|
((ulong) dflt_key_cache->key_cache_mem_size +
|
||||||
|
(global_system_variables.read_buff_size +
|
||||||
|
global_system_variables.sortbuff_size) *
|
||||||
|
thread_scheduler.max_threads +
|
||||||
|
max_connections * sizeof(THD)) / 1024);
|
||||||
|
|
||||||
|
my_safe_printf_stderr("%s",
|
||||||
|
"Hope that's ok; if not, decrease some variables in the equation.\n\n");
|
||||||
|
|
||||||
|
#if defined(HAVE_LINUXTHREADS)
|
||||||
|
if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
|
||||||
|
{
|
||||||
|
my_safe_printf_stderr(
|
||||||
|
"You seem to be running 32-bit Linux and have "
|
||||||
|
"%d concurrent connections.\n"
|
||||||
|
"If you have not changed STACK_SIZE in LinuxThreads "
|
||||||
|
"and built the binary \n"
|
||||||
|
"yourself, LinuxThreads is quite likely to steal "
|
||||||
|
"a part of the global heap for\n"
|
||||||
|
"the thread stack. Please read "
|
||||||
|
"http://dev.mysql.com/doc/mysql/en/linux-installation.html\n\n"
|
||||||
|
thread_count);
|
||||||
|
}
|
||||||
|
#endif /* HAVE_LINUXTHREADS */
|
||||||
|
|
||||||
|
#ifdef HAVE_STACKTRACE
|
||||||
|
THD *thd=current_thd;
|
||||||
|
|
||||||
|
if (!(test_flags & TEST_NO_STACKTRACE))
|
||||||
|
{
|
||||||
|
my_safe_printf_stderr("Thread pointer: 0x%p\n", thd);
|
||||||
|
my_safe_printf_stderr("%s",
|
||||||
|
"Attempting backtrace. You can use the following "
|
||||||
|
"information to find out\n"
|
||||||
|
"where mysqld died. If you see no messages after this, something went\n"
|
||||||
|
"terribly wrong...\n");
|
||||||
|
my_print_stacktrace(thd ? (uchar*) thd->thread_stack : NULL,
|
||||||
|
my_thread_stack_size);
|
||||||
|
}
|
||||||
|
if (thd)
|
||||||
|
{
|
||||||
|
const char *kreason= "UNKNOWN";
|
||||||
|
switch (thd->killed) {
|
||||||
|
case THD::NOT_KILLED:
|
||||||
|
kreason= "NOT_KILLED";
|
||||||
|
break;
|
||||||
|
case THD::KILL_BAD_DATA:
|
||||||
|
kreason= "KILL_BAD_DATA";
|
||||||
|
break;
|
||||||
|
case THD::KILL_CONNECTION:
|
||||||
|
kreason= "KILL_CONNECTION";
|
||||||
|
break;
|
||||||
|
case THD::KILL_QUERY:
|
||||||
|
kreason= "KILL_QUERY";
|
||||||
|
break;
|
||||||
|
case THD::KILLED_NO_VALUE:
|
||||||
|
kreason= "KILLED_NO_VALUE";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
my_safe_printf_stderr("%s", "\n"
|
||||||
|
"Trying to get some variables.\n"
|
||||||
|
"Some pointers may be invalid and cause the dump to abort.\n");
|
||||||
|
|
||||||
|
my_safe_printf_stderr("Query (%p): ", thd->query());
|
||||||
|
my_safe_print_str(thd->query(), min(1024U, thd->query_length()));
|
||||||
|
my_safe_printf_stderr("Connection ID (thread ID): %lu\n",
|
||||||
|
(ulong) thd->thread_id);
|
||||||
|
my_safe_printf_stderr("Status: %s\n\n", kreason);
|
||||||
|
}
|
||||||
|
my_safe_printf_stderr("%s",
|
||||||
|
"The manual page at "
|
||||||
|
"http://dev.mysql.com/doc/mysql/en/crashing.html contains\n"
|
||||||
|
"information that should help you find out what is causing the crash.\n");
|
||||||
|
|
||||||
|
#endif /* HAVE_STACKTRACE */
|
||||||
|
|
||||||
|
#ifdef HAVE_INITGROUPS
|
||||||
|
if (calling_initgroups)
|
||||||
|
{
|
||||||
|
my_safe_printf_stderr("%s", "\n"
|
||||||
|
"This crash occured while the server was calling initgroups(). This is\n"
|
||||||
|
"often due to the use of a mysqld that is statically linked against \n"
|
||||||
|
"glibc and configured to use LDAP in /etc/nsswitch.conf.\n"
|
||||||
|
"You will need to either upgrade to a version of glibc that does not\n"
|
||||||
|
"have this problem (2.3.4 or later when used with nscd),\n"
|
||||||
|
"disable LDAP in your nsswitch.conf, or use a "
|
||||||
|
"mysqld that is not statically linked.\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_NPTL
|
||||||
|
if (thd_lib_detected == THD_LIB_LT && !ld_assume_kernel_is_set)
|
||||||
|
{
|
||||||
|
my_safe_printf_stderr("%s",
|
||||||
|
"You are running a statically-linked LinuxThreads binary on an NPTL\n"
|
||||||
|
"system. This can result in crashes on some distributions due to "
|
||||||
|
"LT/NPTL conflicts.\n"
|
||||||
|
"You should either build a dynamically-linked binary, "
|
||||||
|
"or force LinuxThreads\n"
|
||||||
|
"to be used with the LD_ASSUME_KERNEL environment variable.\n"
|
||||||
|
"Please consult the documentation for your distribution "
|
||||||
|
"on how to do that.\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (locked_in_memory)
|
||||||
|
{
|
||||||
|
my_safe_printf_stderr("%s", "\n"
|
||||||
|
"The \"--memlock\" argument, which was enabled, "
|
||||||
|
"uses system calls that are\n"
|
||||||
|
"unreliable and unstable on some operating systems and "
|
||||||
|
"operating-system versions (notably, some versions of Linux).\n"
|
||||||
|
"This crash could be due to use of those buggy OS calls.\n"
|
||||||
|
"You should consider whether you really need the "
|
||||||
|
"\"--memlock\" parameter and/or consult the OS distributer about "
|
||||||
|
"\"mlockall\" bugs.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_WRITE_CORE
|
||||||
|
if (test_flags & TEST_CORE_ON_SIGNAL)
|
||||||
|
{
|
||||||
|
my_safe_printf_stderr("%s", "Writing a core file\n");
|
||||||
|
my_write_core(sig);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __WIN__
|
||||||
|
/*
|
||||||
|
Quit, without running destructors (etc.)
|
||||||
|
On Windows, do not terminate, but pass control to exception filter.
|
||||||
|
*/
|
||||||
|
_exit(1); // Using _exit(), since exit() is not async signal safe
|
||||||
|
#endif
|
||||||
|
}
|
@ -63,6 +63,8 @@
|
|||||||
#include "slave.h"
|
#include "slave.h"
|
||||||
#include "rpl_mi.h"
|
#include "rpl_mi.h"
|
||||||
|
|
||||||
|
#include "debug_sync.h"
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
static bool delayed_get_table(THD *thd, TABLE_LIST *table_list);
|
static bool delayed_get_table(THD *thd, TABLE_LIST *table_list);
|
||||||
static int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic,
|
static int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic,
|
||||||
@ -1411,6 +1413,8 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||||||
error= HA_ERR_FOUND_DUPP_KEY; /* Database can't find key */
|
error= HA_ERR_FOUND_DUPP_KEY; /* Database can't find key */
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
DEBUG_SYNC(thd, "write_row_replace");
|
||||||
|
|
||||||
/* Read all columns for the row we are going to replace */
|
/* Read all columns for the row we are going to replace */
|
||||||
table->use_all_columns();
|
table->use_all_columns();
|
||||||
/*
|
/*
|
||||||
@ -1604,6 +1608,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||||||
}
|
}
|
||||||
else if ((error=table->file->ha_write_row(table->record[0])))
|
else if ((error=table->file->ha_write_row(table->record[0])))
|
||||||
{
|
{
|
||||||
|
DEBUG_SYNC(thd, "write_row_noreplace");
|
||||||
if (!info->ignore ||
|
if (!info->ignore ||
|
||||||
table->file->is_fatal_error(error, HA_CHECK_DUP))
|
table->file->is_fatal_error(error, HA_CHECK_DUP))
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -10647,6 +10647,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
|||||||
if (open_tmp_table(table))
|
if (open_tmp_table(table))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
// Make empty record so random data is not written to disk
|
||||||
|
empty_record(table);
|
||||||
|
|
||||||
thd->mem_root= mem_root_save;
|
thd->mem_root= mem_root_save;
|
||||||
|
|
||||||
DBUG_RETURN(table);
|
DBUG_RETURN(table);
|
||||||
|
@ -760,6 +760,7 @@ uint32 ha_archive::max_row_length(const uchar *buf)
|
|||||||
ptr != end ;
|
ptr != end ;
|
||||||
ptr++)
|
ptr++)
|
||||||
{
|
{
|
||||||
|
if (!table->field[*ptr]->is_null())
|
||||||
length += 2 + ((Field_blob*)table->field[*ptr])->get_length();
|
length += 2 + ((Field_blob*)table->field[*ptr])->get_length();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1110,6 +1111,17 @@ int ha_archive::unpack_row(azio_stream *file_to_read, uchar *record)
|
|||||||
|
|
||||||
/* Copy null bits */
|
/* Copy null bits */
|
||||||
const uchar *ptr= record_buffer->buffer;
|
const uchar *ptr= record_buffer->buffer;
|
||||||
|
/*
|
||||||
|
Field::unpack() is not called when field is NULL. For VARCHAR
|
||||||
|
Field::unpack() only unpacks as much bytes as occupied by field
|
||||||
|
value. In these cases respective memory area on record buffer is
|
||||||
|
not initialized.
|
||||||
|
|
||||||
|
These uninitialized areas may be accessed by CHECKSUM TABLE or
|
||||||
|
by optimizer using temporary table (BUG#12997905). We may remove
|
||||||
|
this memset() when they're fixed.
|
||||||
|
*/
|
||||||
|
memset(record, 0, table->s->reclength);
|
||||||
memcpy(record, ptr, table->s->null_bytes);
|
memcpy(record, ptr, table->s->null_bytes);
|
||||||
ptr+= table->s->null_bytes;
|
ptr+= table->s->null_bytes;
|
||||||
for (Field **field=table->field ; *field ; field++)
|
for (Field **field=table->field ; *field ; field++)
|
||||||
@ -1578,13 +1590,15 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
|
|||||||
{
|
{
|
||||||
int rc= 0;
|
int rc= 0;
|
||||||
const char *old_proc_info;
|
const char *old_proc_info;
|
||||||
ha_rows count= share->rows_recorded;
|
ha_rows count;
|
||||||
DBUG_ENTER("ha_archive::check");
|
DBUG_ENTER("ha_archive::check");
|
||||||
|
|
||||||
old_proc_info= thd_proc_info(thd, "Checking table");
|
old_proc_info= thd_proc_info(thd, "Checking table");
|
||||||
/* Flush any waiting data */
|
|
||||||
pthread_mutex_lock(&share->mutex);
|
pthread_mutex_lock(&share->mutex);
|
||||||
azflush(&(share->archive_write), Z_SYNC_FLUSH);
|
count= share->rows_recorded;
|
||||||
|
/* Flush any waiting data */
|
||||||
|
if (share->archive_write_open)
|
||||||
|
azflush(&(share->archive_write), Z_SYNC_FLUSH);
|
||||||
pthread_mutex_unlock(&share->mutex);
|
pthread_mutex_unlock(&share->mutex);
|
||||||
|
|
||||||
if (init_archive_reader())
|
if (init_archive_reader())
|
||||||
@ -1594,18 +1608,34 @@ int ha_archive::check(THD* thd, HA_CHECK_OPT* check_opt)
|
|||||||
start of the file.
|
start of the file.
|
||||||
*/
|
*/
|
||||||
read_data_header(&archive);
|
read_data_header(&archive);
|
||||||
|
for (ha_rows cur_count= count; cur_count; cur_count--)
|
||||||
|
{
|
||||||
|
if ((rc= get_row(&archive, table->record[0])))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Now read records that may have been inserted concurrently.
|
||||||
|
Acquire share->mutex so tail of the table is not modified by
|
||||||
|
concurrent writers.
|
||||||
|
*/
|
||||||
|
pthread_mutex_lock(&share->mutex);
|
||||||
|
count= share->rows_recorded - count;
|
||||||
|
if (share->archive_write_open)
|
||||||
|
azflush(&(share->archive_write), Z_SYNC_FLUSH);
|
||||||
while (!(rc= get_row(&archive, table->record[0])))
|
while (!(rc= get_row(&archive, table->record[0])))
|
||||||
count--;
|
count--;
|
||||||
|
pthread_mutex_unlock(&share->mutex);
|
||||||
thd_proc_info(thd, old_proc_info);
|
|
||||||
|
|
||||||
if ((rc && rc != HA_ERR_END_OF_FILE) || count)
|
if ((rc && rc != HA_ERR_END_OF_FILE) || count)
|
||||||
{
|
goto error;
|
||||||
share->crashed= FALSE;
|
|
||||||
DBUG_RETURN(HA_ADMIN_CORRUPT);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
thd_proc_info(thd, old_proc_info);
|
||||||
DBUG_RETURN(HA_ADMIN_OK);
|
DBUG_RETURN(HA_ADMIN_OK);
|
||||||
|
|
||||||
|
error:
|
||||||
|
thd_proc_info(thd, old_proc_info);
|
||||||
|
share->crashed= FALSE;
|
||||||
|
DBUG_RETURN(HA_ADMIN_CORRUPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4087,8 +4087,7 @@ no_commit:
|
|||||||
|
|
||||||
switch (sql_command) {
|
switch (sql_command) {
|
||||||
case SQLCOM_LOAD:
|
case SQLCOM_LOAD:
|
||||||
if ((trx->duplicates
|
if (trx->duplicates) {
|
||||||
& (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
|
|
||||||
|
|
||||||
goto set_max_autoinc;
|
goto set_max_autoinc;
|
||||||
}
|
}
|
||||||
@ -4368,8 +4367,7 @@ ha_innobase::update_row(
|
|||||||
&& table->next_number_field
|
&& table->next_number_field
|
||||||
&& new_row == table->record[0]
|
&& new_row == table->record[0]
|
||||||
&& thd_sql_command(user_thd) == SQLCOM_INSERT
|
&& thd_sql_command(user_thd) == SQLCOM_INSERT
|
||||||
&& (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
|
&& trx->duplicates) {
|
||||||
== TRX_DUP_IGNORE) {
|
|
||||||
|
|
||||||
ulonglong auto_inc;
|
ulonglong auto_inc;
|
||||||
ulonglong col_max_value;
|
ulonglong col_max_value;
|
||||||
@ -4717,6 +4715,7 @@ ha_innobase::index_read(
|
|||||||
index,
|
index,
|
||||||
(byte*) key_ptr,
|
(byte*) key_ptr,
|
||||||
(ulint) key_len, prebuilt->trx);
|
(ulint) key_len, prebuilt->trx);
|
||||||
|
DBUG_ASSERT(prebuilt->search_tuple->n_fields > 0);
|
||||||
} else {
|
} else {
|
||||||
/* We position the cursor to the last or the first entry
|
/* We position the cursor to the last or the first entry
|
||||||
in the index */
|
in the index */
|
||||||
@ -6172,6 +6171,7 @@ ha_innobase::records_in_range(
|
|||||||
void* heap2;
|
void* heap2;
|
||||||
|
|
||||||
DBUG_ENTER("records_in_range");
|
DBUG_ENTER("records_in_range");
|
||||||
|
DBUG_ASSERT(min_key || max_key);
|
||||||
|
|
||||||
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
|
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
|
||||||
|
|
||||||
@ -6202,6 +6202,9 @@ ha_innobase::records_in_range(
|
|||||||
(const uchar*) 0),
|
(const uchar*) 0),
|
||||||
(ulint) (min_key ? min_key->length : 0),
|
(ulint) (min_key ? min_key->length : 0),
|
||||||
prebuilt->trx);
|
prebuilt->trx);
|
||||||
|
DBUG_ASSERT(min_key
|
||||||
|
? range_start->n_fields > 0
|
||||||
|
: range_start->n_fields == 0);
|
||||||
|
|
||||||
row_sel_convert_mysql_key_to_innobase(
|
row_sel_convert_mysql_key_to_innobase(
|
||||||
range_end, (byte*) key_val_buff2,
|
range_end, (byte*) key_val_buff2,
|
||||||
@ -6210,6 +6213,9 @@ ha_innobase::records_in_range(
|
|||||||
(const uchar*) 0),
|
(const uchar*) 0),
|
||||||
(ulint) (max_key ? max_key->length : 0),
|
(ulint) (max_key ? max_key->length : 0),
|
||||||
prebuilt->trx);
|
prebuilt->trx);
|
||||||
|
DBUG_ASSERT(max_key
|
||||||
|
? range_end->n_fields > 0
|
||||||
|
: range_end->n_fields == 0);
|
||||||
|
|
||||||
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
|
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
|
||||||
HA_READ_KEY_EXACT);
|
HA_READ_KEY_EXACT);
|
||||||
@ -7095,6 +7101,7 @@ ha_innobase::extra(
|
|||||||
break;
|
break;
|
||||||
case HA_EXTRA_RESET_STATE:
|
case HA_EXTRA_RESET_STATE:
|
||||||
reset_template(prebuilt);
|
reset_template(prebuilt);
|
||||||
|
thd_to_trx(ha_thd())->duplicates = 0;
|
||||||
break;
|
break;
|
||||||
case HA_EXTRA_NO_KEYREAD:
|
case HA_EXTRA_NO_KEYREAD:
|
||||||
prebuilt->read_just_key = 0;
|
prebuilt->read_just_key = 0;
|
||||||
@ -7112,19 +7119,18 @@ ha_innobase::extra(
|
|||||||
parameters below. We must not invoke update_thd()
|
parameters below. We must not invoke update_thd()
|
||||||
either, because the calling threads may change.
|
either, because the calling threads may change.
|
||||||
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
|
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
|
||||||
case HA_EXTRA_IGNORE_DUP_KEY:
|
case HA_EXTRA_INSERT_WITH_UPDATE:
|
||||||
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
|
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
|
||||||
break;
|
break;
|
||||||
|
case HA_EXTRA_NO_IGNORE_DUP_KEY:
|
||||||
|
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_IGNORE;
|
||||||
|
break;
|
||||||
case HA_EXTRA_WRITE_CAN_REPLACE:
|
case HA_EXTRA_WRITE_CAN_REPLACE:
|
||||||
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
|
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
|
||||||
break;
|
break;
|
||||||
case HA_EXTRA_WRITE_CANNOT_REPLACE:
|
case HA_EXTRA_WRITE_CANNOT_REPLACE:
|
||||||
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
|
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
|
||||||
break;
|
break;
|
||||||
case HA_EXTRA_NO_IGNORE_DUP_KEY:
|
|
||||||
thd_to_trx(ha_thd())->duplicates &=
|
|
||||||
~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
|
|
||||||
break;
|
|
||||||
default:/* Do nothing */
|
default:/* Do nothing */
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -1673,7 +1673,7 @@ row_ins_scan_sec_index_for_duplicate(
|
|||||||
|
|
||||||
btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr);
|
btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||||
|
|
||||||
allow_duplicates = thr_get_trx(thr)->duplicates & TRX_DUP_IGNORE;
|
allow_duplicates = thr_get_trx(thr)->duplicates;
|
||||||
|
|
||||||
/* Scan index records and check if there is a duplicate */
|
/* Scan index records and check if there is a duplicate */
|
||||||
|
|
||||||
@ -1813,7 +1813,7 @@ row_ins_duplicate_error_in_clust(
|
|||||||
sure that in roll-forward we get the same duplicate
|
sure that in roll-forward we get the same duplicate
|
||||||
errors as in original execution */
|
errors as in original execution */
|
||||||
|
|
||||||
if (trx->duplicates & TRX_DUP_IGNORE) {
|
if (trx->duplicates) {
|
||||||
|
|
||||||
/* If the SQL-query will update or replace
|
/* If the SQL-query will update or replace
|
||||||
duplicate key we will take X-lock for
|
duplicate key we will take X-lock for
|
||||||
@ -1855,7 +1855,7 @@ row_ins_duplicate_error_in_clust(
|
|||||||
offsets = rec_get_offsets(rec, cursor->index, offsets,
|
offsets = rec_get_offsets(rec, cursor->index, offsets,
|
||||||
ULINT_UNDEFINED, &heap);
|
ULINT_UNDEFINED, &heap);
|
||||||
|
|
||||||
if (trx->duplicates & TRX_DUP_IGNORE) {
|
if (trx->duplicates) {
|
||||||
|
|
||||||
/* If the SQL-query will update or replace
|
/* If the SQL-query will update or replace
|
||||||
duplicate key we will take X-lock for
|
duplicate key we will take X-lock for
|
||||||
|
@ -1,3 +1,15 @@
|
|||||||
|
2011-11-10 The InnoDB Team
|
||||||
|
|
||||||
|
* handler/ha_innodb.cc, row/row0ins.c, innodb_replace.test:
|
||||||
|
Fix Bug#11759688 52020: InnoDB can still deadlock
|
||||||
|
on just INSERT...ON DUPLICATE KEY a.k.a. the reintroduction of
|
||||||
|
Bug#7975 deadlock without any locking, simple select and update
|
||||||
|
|
||||||
|
2011-11-08 The InnoDB Team
|
||||||
|
|
||||||
|
* btr/btr0pcur.c, include/btr0pcur.h, include/btr0pcur.ic:
|
||||||
|
Fix Bug#13358468 ASSERTION FAILURE IN BTR_PCUR_GET_BLOCK
|
||||||
|
|
||||||
2011-10-27 The InnoDB Team
|
2011-10-27 The InnoDB Team
|
||||||
|
|
||||||
* row/row0mysql.c:
|
* row/row0mysql.c:
|
||||||
@ -55,6 +67,15 @@
|
|||||||
* include/trx0undo.h, trx/trx0rec.c, trx/trx0undo.c:
|
* include/trx0undo.h, trx/trx0rec.c, trx/trx0undo.c:
|
||||||
Fix Bug#12547647 UPDATE LOGGING COULD EXCEED LOG PAGE SIZE
|
Fix Bug#12547647 UPDATE LOGGING COULD EXCEED LOG PAGE SIZE
|
||||||
|
|
||||||
|
2011-08-29 The InnoDB Team
|
||||||
|
|
||||||
|
* btr/btr0btr.c, btr/btr0cur.c, fsp/fsp0fsp.c,
|
||||||
|
include/btr0btr.h, include/btr0cur.h, include/fsp0fsp.h,
|
||||||
|
include/mtr0mtr.h, include/mtr0mtr.ic, mtr/mtr0mtr.c,
|
||||||
|
row/row0ins.c, row/row0row.c, row/row0upd.c, trx/trx0undo.c:
|
||||||
|
Fix Bug#12704861 Corruption after a crash during BLOB update
|
||||||
|
and other regressions from the fix of Bug#12612184
|
||||||
|
|
||||||
2011-08-15 The InnoDB Team
|
2011-08-15 The InnoDB Team
|
||||||
|
|
||||||
* btr/btr0btr.c, btr/btr0cur.c, btr/btr0pcur.c, btr/btr0sea.c,
|
* btr/btr0btr.c, btr/btr0cur.c, btr/btr0pcur.c, btr/btr0sea.c,
|
||||||
@ -106,6 +127,16 @@
|
|||||||
* page/page0zip.c, rem/rem0rec.c:
|
* page/page0zip.c, rem/rem0rec.c:
|
||||||
Fix Bug#61191 question about page_zip_available()
|
Fix Bug#61191 question about page_zip_available()
|
||||||
|
|
||||||
|
2011-06-16 The InnoDB Team
|
||||||
|
|
||||||
|
* btr/btr0btr.c, btr/btr0cur.c, include/btr0btr.h, include/btr0cur.h,
|
||||||
|
include/btr0cur.ic, include/buf0buf.h, include/buf0buf.ic,
|
||||||
|
include/page0cur.ic, include/page0page.h, include/page0page.ic,
|
||||||
|
include/sync0rw.ic, include/sync0sync.h, page/page0cur.c,
|
||||||
|
page/page0page.c, row/row0ins.c, row/row0upd.c,
|
||||||
|
sync/sync0rw.c, sync/sync0sync.c:
|
||||||
|
Fix Bug#12612184 Race condition after btr_cur_pessimistic_update()
|
||||||
|
|
||||||
2011-06-09 The InnoDB Team
|
2011-06-09 The InnoDB Team
|
||||||
* btr/btr0cur.c, include/rem0rec.h, include/rem0rec.ic,
|
* btr/btr0cur.c, include/rem0rec.h, include/rem0rec.ic,
|
||||||
* row/row0row.c, row/row0vers.c, trx/trx0rec.c:
|
* row/row0row.c, row/row0vers.c, trx/trx0rec.c:
|
||||||
|
@ -247,6 +247,8 @@ btr_pcur_restore_position_func(
|
|||||||
cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
|
cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
|
||||||
index, latch_mode, btr_pcur_get_btr_cur(cursor), mtr);
|
index, latch_mode, btr_pcur_get_btr_cur(cursor), mtr);
|
||||||
|
|
||||||
|
cursor->latch_mode = latch_mode;
|
||||||
|
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
|
||||||
cursor->block_when_stored = btr_pcur_get_block(cursor);
|
cursor->block_when_stored = btr_pcur_get_block(cursor);
|
||||||
|
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
|
@ -946,6 +946,24 @@ buf_pool_free(void)
|
|||||||
{
|
{
|
||||||
buf_chunk_t* chunk;
|
buf_chunk_t* chunk;
|
||||||
buf_chunk_t* chunks;
|
buf_chunk_t* chunks;
|
||||||
|
buf_page_t* bpage;
|
||||||
|
|
||||||
|
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
|
||||||
|
while (bpage != NULL) {
|
||||||
|
buf_page_t* prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
|
||||||
|
enum buf_page_state state = buf_page_get_state(bpage);
|
||||||
|
|
||||||
|
ut_ad(buf_page_in_file(bpage));
|
||||||
|
ut_ad(bpage->in_LRU_list);
|
||||||
|
|
||||||
|
if (state != BUF_BLOCK_FILE_PAGE) {
|
||||||
|
/* We must not have any dirty block. */
|
||||||
|
ut_ad(state == BUF_BLOCK_ZIP_PAGE);
|
||||||
|
buf_page_free_descriptor(bpage);
|
||||||
|
}
|
||||||
|
|
||||||
|
bpage = prev_bpage;
|
||||||
|
}
|
||||||
|
|
||||||
chunks = buf_pool->chunks;
|
chunks = buf_pool->chunks;
|
||||||
chunk = chunks + buf_pool->n_chunks;
|
chunk = chunks + buf_pool->n_chunks;
|
||||||
|
@ -4793,8 +4793,7 @@ no_commit:
|
|||||||
|
|
||||||
switch (sql_command) {
|
switch (sql_command) {
|
||||||
case SQLCOM_LOAD:
|
case SQLCOM_LOAD:
|
||||||
if ((trx->duplicates
|
if (trx->duplicates) {
|
||||||
& (TRX_DUP_IGNORE | TRX_DUP_REPLACE))) {
|
|
||||||
|
|
||||||
goto set_max_autoinc;
|
goto set_max_autoinc;
|
||||||
}
|
}
|
||||||
@ -5070,8 +5069,7 @@ ha_innobase::update_row(
|
|||||||
&& table->next_number_field
|
&& table->next_number_field
|
||||||
&& new_row == table->record[0]
|
&& new_row == table->record[0]
|
||||||
&& thd_sql_command(user_thd) == SQLCOM_INSERT
|
&& thd_sql_command(user_thd) == SQLCOM_INSERT
|
||||||
&& (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
|
&& trx->duplicates) {
|
||||||
== TRX_DUP_IGNORE) {
|
|
||||||
|
|
||||||
ulonglong auto_inc;
|
ulonglong auto_inc;
|
||||||
ulonglong col_max_value;
|
ulonglong col_max_value;
|
||||||
@ -5429,6 +5427,7 @@ ha_innobase::index_read(
|
|||||||
(byte*) key_ptr,
|
(byte*) key_ptr,
|
||||||
(ulint) key_len,
|
(ulint) key_len,
|
||||||
prebuilt->trx);
|
prebuilt->trx);
|
||||||
|
DBUG_ASSERT(prebuilt->search_tuple->n_fields > 0);
|
||||||
} else {
|
} else {
|
||||||
/* We position the cursor to the last or the first entry
|
/* We position the cursor to the last or the first entry
|
||||||
in the index */
|
in the index */
|
||||||
@ -7227,6 +7226,7 @@ ha_innobase::records_in_range(
|
|||||||
mem_heap_t* heap;
|
mem_heap_t* heap;
|
||||||
|
|
||||||
DBUG_ENTER("records_in_range");
|
DBUG_ENTER("records_in_range");
|
||||||
|
DBUG_ASSERT(min_key || max_key);
|
||||||
|
|
||||||
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
|
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
|
||||||
|
|
||||||
@ -7272,6 +7272,9 @@ ha_innobase::records_in_range(
|
|||||||
(const uchar*) 0),
|
(const uchar*) 0),
|
||||||
(ulint) (min_key ? min_key->length : 0),
|
(ulint) (min_key ? min_key->length : 0),
|
||||||
prebuilt->trx);
|
prebuilt->trx);
|
||||||
|
DBUG_ASSERT(min_key
|
||||||
|
? range_start->n_fields > 0
|
||||||
|
: range_start->n_fields == 0);
|
||||||
|
|
||||||
row_sel_convert_mysql_key_to_innobase(
|
row_sel_convert_mysql_key_to_innobase(
|
||||||
range_end, (byte*) key_val_buff2,
|
range_end, (byte*) key_val_buff2,
|
||||||
@ -7280,6 +7283,9 @@ ha_innobase::records_in_range(
|
|||||||
(const uchar*) 0),
|
(const uchar*) 0),
|
||||||
(ulint) (max_key ? max_key->length : 0),
|
(ulint) (max_key ? max_key->length : 0),
|
||||||
prebuilt->trx);
|
prebuilt->trx);
|
||||||
|
DBUG_ASSERT(max_key
|
||||||
|
? range_end->n_fields > 0
|
||||||
|
: range_end->n_fields == 0);
|
||||||
|
|
||||||
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
|
mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
|
||||||
HA_READ_KEY_EXACT);
|
HA_READ_KEY_EXACT);
|
||||||
@ -8416,6 +8422,7 @@ ha_innobase::extra(
|
|||||||
break;
|
break;
|
||||||
case HA_EXTRA_RESET_STATE:
|
case HA_EXTRA_RESET_STATE:
|
||||||
reset_template(prebuilt);
|
reset_template(prebuilt);
|
||||||
|
thd_to_trx(ha_thd())->duplicates = 0;
|
||||||
break;
|
break;
|
||||||
case HA_EXTRA_NO_KEYREAD:
|
case HA_EXTRA_NO_KEYREAD:
|
||||||
prebuilt->read_just_key = 0;
|
prebuilt->read_just_key = 0;
|
||||||
@ -8433,19 +8440,18 @@ ha_innobase::extra(
|
|||||||
parameters below. We must not invoke update_thd()
|
parameters below. We must not invoke update_thd()
|
||||||
either, because the calling threads may change.
|
either, because the calling threads may change.
|
||||||
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
|
CAREFUL HERE, OR MEMORY CORRUPTION MAY OCCUR! */
|
||||||
case HA_EXTRA_IGNORE_DUP_KEY:
|
case HA_EXTRA_INSERT_WITH_UPDATE:
|
||||||
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
|
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_IGNORE;
|
||||||
break;
|
break;
|
||||||
|
case HA_EXTRA_NO_IGNORE_DUP_KEY:
|
||||||
|
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_IGNORE;
|
||||||
|
break;
|
||||||
case HA_EXTRA_WRITE_CAN_REPLACE:
|
case HA_EXTRA_WRITE_CAN_REPLACE:
|
||||||
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
|
thd_to_trx(ha_thd())->duplicates |= TRX_DUP_REPLACE;
|
||||||
break;
|
break;
|
||||||
case HA_EXTRA_WRITE_CANNOT_REPLACE:
|
case HA_EXTRA_WRITE_CANNOT_REPLACE:
|
||||||
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
|
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
|
||||||
break;
|
break;
|
||||||
case HA_EXTRA_NO_IGNORE_DUP_KEY:
|
|
||||||
thd_to_trx(ha_thd())->duplicates &=
|
|
||||||
~(TRX_DUP_IGNORE | TRX_DUP_REPLACE);
|
|
||||||
break;
|
|
||||||
default:/* Do nothing */
|
default:/* Do nothing */
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -279,14 +279,6 @@ btr_pcur_commit_specify_mtr(
|
|||||||
/*========================*/
|
/*========================*/
|
||||||
btr_pcur_t* pcur, /*!< in: persistent cursor */
|
btr_pcur_t* pcur, /*!< in: persistent cursor */
|
||||||
mtr_t* mtr); /*!< in: mtr to commit */
|
mtr_t* mtr); /*!< in: mtr to commit */
|
||||||
/**************************************************************//**
|
|
||||||
Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
|
|
||||||
@return TRUE if detached */
|
|
||||||
UNIV_INLINE
|
|
||||||
ibool
|
|
||||||
btr_pcur_is_detached(
|
|
||||||
/*=================*/
|
|
||||||
btr_pcur_t* pcur); /*!< in: persistent cursor */
|
|
||||||
/*********************************************************//**
|
/*********************************************************//**
|
||||||
Moves the persistent cursor to the next record in the tree. If no records are
|
Moves the persistent cursor to the next record in the tree. If no records are
|
||||||
left, the cursor stays 'after last in tree'.
|
left, the cursor stays 'after last in tree'.
|
||||||
|
@ -415,38 +415,6 @@ btr_pcur_commit_specify_mtr(
|
|||||||
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
|
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************//**
|
|
||||||
Sets the pcur latch mode to BTR_NO_LATCHES. */
|
|
||||||
UNIV_INLINE
|
|
||||||
void
|
|
||||||
btr_pcur_detach(
|
|
||||||
/*============*/
|
|
||||||
btr_pcur_t* pcur) /*!< in: persistent cursor */
|
|
||||||
{
|
|
||||||
ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
|
|
||||||
|
|
||||||
pcur->latch_mode = BTR_NO_LATCHES;
|
|
||||||
|
|
||||||
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************//**
|
|
||||||
Tests if a cursor is detached: that is the latch mode is BTR_NO_LATCHES.
|
|
||||||
@return TRUE if detached */
|
|
||||||
UNIV_INLINE
|
|
||||||
ibool
|
|
||||||
btr_pcur_is_detached(
|
|
||||||
/*=================*/
|
|
||||||
btr_pcur_t* pcur) /*!< in: persistent cursor */
|
|
||||||
{
|
|
||||||
if (pcur->latch_mode == BTR_NO_LATCHES) {
|
|
||||||
|
|
||||||
return(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************//**
|
/**************************************************************//**
|
||||||
Sets the old_rec_buf field to NULL. */
|
Sets the old_rec_buf field to NULL. */
|
||||||
UNIV_INLINE
|
UNIV_INLINE
|
||||||
|
@ -1665,7 +1665,7 @@ row_ins_scan_sec_index_for_duplicate(
|
|||||||
ulint n_fields_cmp;
|
ulint n_fields_cmp;
|
||||||
btr_pcur_t pcur;
|
btr_pcur_t pcur;
|
||||||
ulint err = DB_SUCCESS;
|
ulint err = DB_SUCCESS;
|
||||||
unsigned allow_duplicates;
|
ulint allow_duplicates;
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
mem_heap_t* heap = NULL;
|
mem_heap_t* heap = NULL;
|
||||||
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
||||||
@ -1696,7 +1696,7 @@ row_ins_scan_sec_index_for_duplicate(
|
|||||||
|
|
||||||
btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr);
|
btr_pcur_open(index, entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||||
|
|
||||||
allow_duplicates = thr_get_trx(thr)->duplicates & TRX_DUP_IGNORE;
|
allow_duplicates = thr_get_trx(thr)->duplicates;
|
||||||
|
|
||||||
/* Scan index records and check if there is a duplicate */
|
/* Scan index records and check if there is a duplicate */
|
||||||
|
|
||||||
@ -1830,7 +1830,7 @@ row_ins_duplicate_error_in_clust(
|
|||||||
sure that in roll-forward we get the same duplicate
|
sure that in roll-forward we get the same duplicate
|
||||||
errors as in original execution */
|
errors as in original execution */
|
||||||
|
|
||||||
if (trx->duplicates & TRX_DUP_IGNORE) {
|
if (trx->duplicates) {
|
||||||
|
|
||||||
/* If the SQL-query will update or replace
|
/* If the SQL-query will update or replace
|
||||||
duplicate key we will take X-lock for
|
duplicate key we will take X-lock for
|
||||||
@ -1874,7 +1874,7 @@ row_ins_duplicate_error_in_clust(
|
|||||||
offsets = rec_get_offsets(rec, cursor->index, offsets,
|
offsets = rec_get_offsets(rec, cursor->index, offsets,
|
||||||
ULINT_UNDEFINED, &heap);
|
ULINT_UNDEFINED, &heap);
|
||||||
|
|
||||||
if (trx->duplicates & TRX_DUP_IGNORE) {
|
if (trx->duplicates) {
|
||||||
|
|
||||||
/* If the SQL-query will update or replace
|
/* If the SQL-query will update or replace
|
||||||
duplicate key we will take X-lock for
|
duplicate key we will take X-lock for
|
||||||
|
@ -87,7 +87,12 @@ int mi_close(register MI_INFO *info)
|
|||||||
}
|
}
|
||||||
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
||||||
if (share->file_map)
|
if (share->file_map)
|
||||||
_mi_unmap_file(info);
|
{
|
||||||
|
if (share->options & HA_OPTION_COMPRESS_RECORD)
|
||||||
|
_mi_unmap_file(info);
|
||||||
|
else
|
||||||
|
mi_munmap_file(info);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (share->decode_trees)
|
if (share->decode_trees)
|
||||||
{
|
{
|
||||||
|
@ -1553,13 +1553,14 @@ my_bool _mi_memmap_file(MI_INFO *info)
|
|||||||
|
|
||||||
void _mi_unmap_file(MI_INFO *info)
|
void _mi_unmap_file(MI_INFO *info)
|
||||||
{
|
{
|
||||||
VOID(my_munmap((char*) info->s->file_map,
|
DBUG_ASSERT(info->s->options & HA_OPTION_COMPRESS_RECORD);
|
||||||
(size_t) info->s->mmaped_length + MEMMAP_EXTRA_MARGIN));
|
|
||||||
|
VOID(my_munmap((char*) info->s->file_map, (size_t) info->s->mmaped_length));
|
||||||
|
|
||||||
if (myisam_mmap_size != SIZE_T_MAX)
|
if (myisam_mmap_size != SIZE_T_MAX)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&THR_LOCK_myisam_mmap);
|
pthread_mutex_lock(&THR_LOCK_myisam_mmap);
|
||||||
myisam_mmap_used-= info->s->mmaped_length + MEMMAP_EXTRA_MARGIN;
|
myisam_mmap_used-= info->s->mmaped_length;
|
||||||
pthread_mutex_unlock(&THR_LOCK_myisam_mmap);
|
pthread_mutex_unlock(&THR_LOCK_myisam_mmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user