diff options
author | Alexey Kopytov <Alexey.Kopytov@Sun.com> | 2010-08-26 16:36:48 +0400 |
---|---|---|
committer | Alexey Kopytov <Alexey.Kopytov@Sun.com> | 2010-08-26 16:36:48 +0400 |
commit | 2df3a61c3febba980e955158c8e46f575c1a03c4 (patch) | |
tree | b8d0085ad17c77e369ac166492efbb6f54155701 | |
parent | 756076bd23d9e194d5730745d07ee86aa543d4e5 (diff) | |
parent | 0648087ca035bf3aebd4e886f11eec8ebdd4366c (diff) | |
download | mariadb-git-2df3a61c3febba980e955158c8e46f575c1a03c4.tar.gz |
Automerge.
-rw-r--r-- | client/mysqltest.cc | 6 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/innodb_mysql.result | 58 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb_mysql.test | 30 | ||||
-rw-r--r-- | sql/log.cc | 117 | ||||
-rw-r--r-- | sql/mysqld.cc | 19 | ||||
-rw-r--r-- | sql/sql_select.cc | 60 |
6 files changed, 218 insertions, 72 deletions
diff --git a/client/mysqltest.cc b/client/mysqltest.cc index f4fe149f5b5..c39ba4ff6ce 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -5220,8 +5220,10 @@ void do_connect(struct st_command *command) } #endif +#ifndef EMBEDDED_LIBRARY if (opt_protocol) mysql_options(&con_slot->mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol); +#endif #ifdef HAVE_SMEM if (con_shm) @@ -6179,8 +6181,10 @@ get_one_option(int optid, const struct my_option *opt, print_version(); exit(0); case OPT_MYSQL_PROTOCOL: +#ifndef EMBEDDED_LIBRARY opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib, opt->name); +#endif break; case '?': usage(); @@ -7932,8 +7936,10 @@ int main(int argc, char **argv) mysql_options(&con->mysql, MYSQL_SET_CHARSET_DIR, opt_charsets_dir); +#ifndef EMBEDDED_LIBRARY if (opt_protocol) mysql_options(&con->mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol); +#endif #ifdef HAVE_OPENSSL diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result index 23619b91fbc..ba8ac0ba86c 100644 --- a/mysql-test/suite/innodb/r/innodb_mysql.result +++ b/mysql-test/suite/innodb/r/innodb_mysql.result @@ -2529,4 +2529,62 @@ SELECT * FROM t1 FOR UPDATE; SELECT * FROM t1 GROUP BY (SELECT a FROM t2 LIMIT 1 FOR UPDATE) + t1.a; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction DROP TABLE t1,t2; +# +# Bug#55656: mysqldump can be slower after bug #39653 fix +# +CREATE TABLE t1 (a INT , b INT, c INT, d INT, +KEY (b), PRIMARY KEY (a,b)) ENGINE=INNODB; +INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3); +EXPLAIN SELECT COUNT(*) FROM t1; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key b +key_len 4 +ref NULL +rows 3 +Extra Using index +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b); +EXPLAIN SELECT COUNT(*) FROM t1; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key b +key_len 8 +ref NULL +rows 3 +Extra Using index +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b,c); +EXPLAIN SELECT COUNT(*) FROM t1; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key b +key_len 13 +ref NULL +rows 3 +Extra Using index +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b,c,d); +EXPLAIN SELECT COUNT(*) FROM t1; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key PRIMARY +key_len 8 +ref NULL +rows 3 +Extra Using index +DROP TABLE t1; +# End of 5.1 tests diff --git a/mysql-test/suite/innodb/t/innodb_mysql.test b/mysql-test/suite/innodb/t/innodb_mysql.test index d633cb2222e..ae03bebfbe3 100644 --- a/mysql-test/suite/innodb/t/innodb_mysql.test +++ b/mysql-test/suite/innodb/t/innodb_mysql.test @@ -768,9 +768,14 @@ START TRANSACTION; SELECT * FROM t1 LOCK IN SHARE MODE; connection con1; +let $conn_id= `SELECT CONNECTION_ID()`; --send SELECT * FROM t1 FOR UPDATE connection con2; +let $wait_timeout= 2; +let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST +WHERE ID=$conn_id AND STATE='Sending data'; +--source include/wait_condition.inc --echo # should not crash --error ER_LOCK_DEADLOCK SELECT * FROM t1 GROUP BY (SELECT a FROM t2 LIMIT 1 FOR UPDATE) + t1.a; @@ -781,5 +786,30 @@ disconnect con2; DROP TABLE t1,t2; +--echo # +--echo # Bug#55656: mysqldump can be slower after bug #39653 fix +--echo # + +CREATE TABLE t1 (a INT , b INT, c INT, d INT, + KEY (b), PRIMARY KEY (a,b)) ENGINE=INNODB; +INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3); +--query_vertical EXPLAIN SELECT COUNT(*) FROM t1 + +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b); +--query_vertical EXPLAIN SELECT COUNT(*) FROM t1 + +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b,c); +--query_vertical EXPLAIN SELECT COUNT(*) FROM t1 + +DROP INDEX b ON t1; +CREATE INDEX b ON t1(a,b,c,d); +--query_vertical EXPLAIN SELECT COUNT(*) FROM t1 + +DROP TABLE t1; + +--echo # + --echo End of 5.1 tests diff --git a/sql/log.cc b/sql/log.cc index 3f41bf1c929..156c293e3aa 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -5063,70 +5063,93 @@ void sql_perror(const char *message) } +#ifdef __WIN__ +extern "C" my_bool reopen_fstreams(const char *filename, + FILE *outstream, FILE *errstream) +{ + int handle_fd; + int stream_fd; + HANDLE osfh; + + DBUG_ASSERT(filename && (outstream || errstream)); + + if ((osfh= CreateFile(filename, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | + FILE_SHARE_DELETE, NULL, + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, + NULL)) == INVALID_HANDLE_VALUE) + return TRUE; + + if ((handle_fd= _open_osfhandle((intptr_t)osfh, + _O_APPEND | _O_TEXT)) == -1) + { + CloseHandle(osfh); + return TRUE; + } + + if (outstream) + { + stream_fd= _fileno(outstream); + if (_dup2(handle_fd, stream_fd) < 0) + { + CloseHandle(osfh); + return TRUE; + } + } + + if (errstream) + { + stream_fd= _fileno(errstream); + if (_dup2(handle_fd, stream_fd) < 0) + { + CloseHandle(osfh); + return TRUE; + } + } + + _close(handle_fd); + return FALSE; +} +#else +extern "C" my_bool reopen_fstreams(const char *filename, + FILE *outstream, FILE *errstream) +{ + if (outstream && !freopen(filename, "a+", outstream)) + return TRUE; + + if (errstream && !freopen(filename, "a+", errstream)) + return TRUE; + + return FALSE; +} +#endif + + /* Unfortunately, there seems to be no good way to restore the original streams upon failure. */ static bool redirect_std_streams(const char *file) { - if (freopen(file, "a+", stdout) && freopen(file, "a+", stderr)) - { - setbuf(stderr, NULL); - return FALSE; - } + if (reopen_fstreams(file, stdout, stderr)) + return TRUE; - return TRUE; + setbuf(stderr, NULL); + return FALSE; } bool flush_error_log() { - bool result=0; + bool result= 0; if (opt_error_log) { - char err_renamed[FN_REFLEN], *end; - end= strmake(err_renamed,log_error_file,FN_REFLEN-5); - strmov(end, "-old"); VOID(pthread_mutex_lock(&LOCK_error_log)); -#ifdef __WIN__ - char err_temp[FN_REFLEN+5]; - /* - On Windows is necessary a temporary file for to rename - the current error file. - */ - strxmov(err_temp, err_renamed,"-tmp",NullS); - (void) my_delete(err_temp, MYF(0)); - if (freopen(err_temp,"a+",stdout)) - { - int fd; - size_t bytes; - uchar buf[IO_SIZE]; - - freopen(err_temp,"a+",stderr); - setbuf(stderr, NULL); - (void) my_delete(err_renamed, MYF(0)); - my_rename(log_error_file,err_renamed,MYF(0)); - redirect_std_streams(log_error_file); - - if ((fd = my_open(err_temp, O_RDONLY, MYF(0))) >= 0) - { - while ((bytes= my_read(fd, buf, IO_SIZE, MYF(0))) && - bytes != MY_FILE_ERROR) - my_fwrite(stderr, buf, bytes, MYF(0)); - my_close(fd, MYF(0)); - } - (void) my_delete(err_temp, MYF(0)); - } - else - result= 1; -#else - my_rename(log_error_file,err_renamed,MYF(0)); - if (redirect_std_streams(log_error_file)) - result= 1; -#endif + if (redirect_std_streams(log_error_file)) + result= 1; VOID(pthread_mutex_unlock(&LOCK_error_log)); } - return result; + return result; } void MYSQL_BIN_LOG::signal_update() diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 08407d52e09..d9c4c7fc3f5 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -199,6 +199,9 @@ typedef fp_except fp_except_t; # endif #endif +extern "C" my_bool reopen_fstreams(const char *filename, + FILE *outstream, FILE *errstream); + inline void setup_fpu() { #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) @@ -3821,13 +3824,15 @@ static int init_server_components() opt_error_log= 1; // Too long file name else { + my_bool res; #ifndef EMBEDDED_LIBRARY - if (freopen(log_error_file, "a+", stdout)) + res= reopen_fstreams(log_error_file, stdout, stderr); +#else + res= reopen_fstreams(log_error_file, NULL, stderr); #endif - { - if (freopen(log_error_file, "a+", stderr)) - setbuf(stderr, NULL); - } + + if (!res) + setbuf(stderr, NULL); } } @@ -4475,8 +4480,8 @@ we force server id to 2, but this MySQL server will not act as a slave."); #ifdef __WIN__ if (!opt_console) { - freopen(log_error_file,"a+",stdout); - freopen(log_error_file,"a+",stderr); + if (reopen_fstreams(log_error_file, stdout, stderr)) + unireg_abort(1); setbuf(stderr, NULL); FreeConsole(); // Remove window } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7ee1762295f..4a32ca34790 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13017,6 +13017,34 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, } +/** + Find shortest key suitable for full table scan. + + @param table Table to scan + @param usable_keys Allowed keys + + @note + As far as + 1) clustered primary key entry data set is a set of all record + fields (key fields and not key fields) and + 2) secondary index entry data is a union of its key fields and + primary key fields (at least InnoDB and its derivatives don't + duplicate primary key fields there, even if the primary and + the secondary keys have a common subset of key fields), + then secondary index entry data is always a subset of primary key entry. + Unfortunately, key_info[nr].key_length doesn't show the length + of key/pointer pair but a sum of key field lengths only, thus + we can't estimate index IO volume comparing only this key_length + value of secondary keys and clustered PK. + So, try secondary keys first, and choose PK only if there are no + usable secondary covering keys or found best secondary key include + all table fields (i.e. same as PK): + + @return + MAX_KEY no suitable key found + key index otherwise +*/ + uint find_shortest_key(TABLE *table, const key_map *usable_keys) { uint best= MAX_KEY; @@ -13029,23 +13057,6 @@ uint find_shortest_key(TABLE *table, const key_map *usable_keys) uint min_length= (uint) ~0; for (uint nr=0; nr < table->s->keys ; nr++) { - /* - As far as - 1) clustered primary key entry data set is a set of all record - fields (key fields and not key fields) and - 2) secondary index entry data is a union of its key fields and - primary key fields (at least InnoDB and its derivatives don't - duplicate primary key fields there, even if the primary and - the secondary keys have a common subset of key fields), - then secondary index entry data is always a subset of primary key - entry, and the PK is always longer. - Unfortunately, key_info[nr].key_length doesn't show the length - of key/pointer pair but a sum of key field lengths only, thus - we can't estimate index IO volume comparing only this key_length - value of seconday keys and clustered PK. - So, try secondary keys first, and choose PK only if there are no - usable secondary covering keys: - */ if (nr == usable_clustered_pk) continue; if (usable_keys->is_set(nr)) @@ -13058,7 +13069,20 @@ uint find_shortest_key(TABLE *table, const key_map *usable_keys) } } } - return best != MAX_KEY ? best : usable_clustered_pk; + if (usable_clustered_pk != MAX_KEY) + { + /* + If the primary key is clustered and found shorter key covers all table + fields then primary key scan normally would be faster because amount of + data to scan is the same but PK is clustered. + It's safe to compare key parts with table fields since duplicate key + parts aren't allowed. + */ + if (best == MAX_KEY || + table->key_info[best].key_parts >= table->s->fields) + best= usable_clustered_pk; + } + return best; } /** |