Merge 10.2 to 10.3

This commit is contained in:
Marko Mäkelä 2019-08-13 19:28:51 +03:00
commit 65d48b4a7b
81 changed files with 1703 additions and 987 deletions

View file

@ -17,7 +17,7 @@
path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium64_cflags $debug_cflags -lasan -O -g -fsanitize=address"
extra_flags="$pentium64_cflags $debug_cflags -lasan -O -g -fsanitize=address -USAFEMALLOC -UFORCE_INIT_OF_VARS -Wno-uninitialized -Wno-maybe-uninitialized"
extra_configs="$pentium_configs $debug_configs $valgrind_configs $max_configs $disable_asan_plugins"
export LDFLAGS="-ldl"

View file

@ -568,7 +568,8 @@ is_page_corrupted(
page_size);
if (is_corrupted && log_file) {
fprintf(log_file,
"Page " ULINTPF ":%llu may be corrupted;"
"[page id: space=" ULINTPF
", page_number=%llu] may be corrupted;"
" key_version=%u\n",
space_id, cur_page_num,
mach_read_from_4(

View file

@ -1295,7 +1295,7 @@ struct my_option xb_server_options[] =
{"innodb_log_file_size", OPT_INNODB_LOG_FILE_SIZE,
"Ignored for mysqld option compatibility",
(G_PTR*) &srv_log_file_size, (G_PTR*) &srv_log_file_size, 0,
GET_ULL, REQUIRED_ARG, 48 << 20, 1 << 20, 512ULL << 30, 0,
GET_ULL, REQUIRED_ARG, 48 << 20, 1 << 20, log_group_max_size, 0,
UNIV_PAGE_SIZE_MAX, 0},
{"innodb_log_files_in_group", OPT_INNODB_LOG_FILES_IN_GROUP,
"Ignored for mysqld option compatibility",

View file

@ -55,12 +55,19 @@ https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning */
#endif /* HAVE_VALGRIND_MEMCHECK_H */
#if defined(TRASH_FREED_MEMORY)
/* NOTE: Do not invoke TRASH_FILL directly! Use TRASH_ALLOC or TRASH_FREE.
The MEM_UNDEFINED() call before memset() is for canceling the effect
of any previous MEM_NOACCESS(). We must invoke MEM_UNDEFINED() after
writing the dummy pattern, unless MEM_NOACCESS() is going to be invoked.
On AddressSanitizer, the MEM_UNDEFINED() in TRASH_ALLOC() has no effect. */
#define TRASH_FILL(A,B,C) do { const size_t trash_tmp= (B); MEM_UNDEFINED(A, trash_tmp); memset(A, C, trash_tmp); } while (0)
#else
#define TRASH_FILL(A,B,C) do { MEM_UNDEFINED((A), (B)); } while (0)
#define TRASH_FILL(A,B,C) while (0)
#endif
/** Note that some memory became allocated or uninitialized. */
#define TRASH_ALLOC(A,B) do { TRASH_FILL(A,B,0xA5); MEM_UNDEFINED(A,B); } while(0)
/** Note that some memory became freed. (Prohibit further access to it.) */
#define TRASH_FREE(A,B) do { TRASH_FILL(A,B,0x8F); MEM_NOACCESS(A,B); } while(0)
#endif /* MY_VALGRIND_INCLUDED */

View file

@ -69,7 +69,7 @@ if (!$_slave_param_comparison)
if ($rpl_debug)
{
--echo Waiting until '$slave_param' $_slave_param_comparison '$slave_param_value' [timeout='$_slave_timeout', \$slave_error_param='$slave_error_param']
--echo Waiting until '$slave_param' $_slave_param_comparison '$slave_param_value' [\$slave_error_param='$slave_error_param']
}
--let $_slave_check_configured= query_get_value("SHOW SLAVE STATUS", Slave_IO_Running, 1)

View file

@ -17,6 +17,7 @@ drop user bad;
#
set global debug_dbug='+d,auth_invalid_plugin';
create user 'bad' identified by 'worse';
--replace_regex /loaded: [^\n]*/loaded: invalid plugin name/
--error 1
--exec $MYSQL --default-auth=mysql_old_password --user=bad --password=worse 2>&1
set global debug_dbug=@old_dbug;

View file

@ -399,3 +399,19 @@ DROP USER u1@localhost;
SET DEBUG_SYNC = 'RESET';
DROP FUNCTION MY_KILL;
set global sql_mode=default;
#
# MDEV-17998
# Deadlock and eventual Assertion `!table->pos_in_locked_tables' failed
# in tc_release_table on KILL_TIMEOUT
#
SET max_statement_time= 2;
CREATE TABLE t1 (a INT);
CREATE VIEW v1 AS SELECT * FROM t1;
CREATE TABLE t2 (b INT, c INT);
LOCK TABLES v1 READ, t2 WRITE, t1 WRITE;
ALTER TABLE t1 CHANGE f1 f2 DOUBLE;
Got one of the listed errors
ALTER TABLE t2 DROP c;
UNLOCK TABLES;
DROP VIEW v1;
DROP TABLE t1, t2;

View file

@ -642,3 +642,23 @@ SET DEBUG_SYNC = 'RESET';
DROP FUNCTION MY_KILL;
set global sql_mode=default;
--echo #
--echo # MDEV-17998
--echo # Deadlock and eventual Assertion `!table->pos_in_locked_tables' failed
--echo # in tc_release_table on KILL_TIMEOUT
--echo #
SET max_statement_time= 2;
CREATE TABLE t1 (a INT);
CREATE VIEW v1 AS SELECT * FROM t1;
CREATE TABLE t2 (b INT, c INT);
LOCK TABLES v1 READ, t2 WRITE, t1 WRITE;
--error ER_BAD_FIELD_ERROR,ER_STATEMENT_TIMEOUT
ALTER TABLE t1 CHANGE f1 f2 DOUBLE;
ALTER TABLE t2 DROP c;
UNLOCK TABLES;
DROP VIEW v1;
DROP TABLE t1, t2;

View file

@ -3329,6 +3329,7 @@ sub mysql_install_db {
# Create the bootstrap.sql file
# ----------------------------------------------------------------------
my $bootstrap_sql_file= "$opt_vardir/log/bootstrap.sql";
$ENV{'MYSQL_BOOTSTRAP_SQL_FILE'}= $bootstrap_sql_file;
if (! -e $bootstrap_sql_file)
{

View file

@ -2675,6 +2675,8 @@ Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. CREATE... REPLACE SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are replaced. This order cannot be predicted and may differ on master and the slave
INSERT INTO insert_2_keys VALUES (1, 2)
ON DUPLICATE KEY UPDATE a=VALUES(a)+10, b=VALUES(b)+10;
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
DROP TABLE filler_table;
DROP TABLE insert_table;
DROP TABLE update_table;

View file

@ -11,9 +11,6 @@
##############################################################################
MW-286 : MDEV-19992 Galera test failure on MW-286
MW-328A : MDEV-17847 Galera test failure on MW-328[A|B|C]
MW-328B : MDEV-17847 Galera test failure on MW-328[A|B|C]
MW-328C : MDEV-17847 Galera test failure on MW-328[A|B|C]
MW-329 : MDEV-19962 Galera test failure on MW-329
MW-388: MDEV-19803 Long semaphore wait error on galera.MW-388
galera_account_management : MariaDB 10.0 does not support ALTER USER

View file

@ -14,14 +14,29 @@ connection node_1X;
CALL proc_update();;
connection node_2;
SET SESSION wsrep_retry_autocommit = 0;
have_successes
1
have_deadlocks
1
connection node_1;
connection node_1X;
Got one of the listed errors
connection node_1;
DROP PROCEDURE proc_update;
DROP TABLE t1, t2;
CALL mtr.add_suppression("conflict state 3 after post commit");
CALL mtr.add_suppression("conflict state ABORTED after post commit");
connection node_1;
CREATE TABLE t1 (i int primary key, j int) engine=innodb;
INSERT INTO t1 values (1,0);
BEGIN;
UPDATE t1 SET j=1 WHERE i=1;
connection node_2;
UPDATE t1 SET j=2 WHERE i=1;
connection node_1;
COMMIT;
ERROR 40001: Deadlock: wsrep aborted transaction
SELECT * FROM t1;
i j
1 2
connection node_2;
SELECT * FROM t1;
i j
1 2
connection node_1;
DROP TABLE t1;

View file

@ -20,4 +20,4 @@ Got one of the listed errors
connection node_1;
DROP PROCEDURE proc_update;
DROP TABLE t1, t2;
CALL mtr.add_suppression("conflict state 3 after post commit");
CALL mtr.add_suppression("conflict state ABORTED after post commit");

View file

@ -20,4 +20,4 @@ Got one of the listed errors
connection node_1;
DROP PROCEDURE proc_update;
DROP TABLE t1, t2;
CALL mtr.add_suppression("conflict state 3 after post commit");
CALL mtr.add_suppression("conflict state ABORTED after post commit");

View file

@ -0,0 +1,44 @@
use performance_schema;
SELECT name
FROM threads
WHERE name LIKE 'thread/sql/wsrep%'
ORDER BY name;
name thread/sql/wsrep_applier_thread
name thread/sql/wsrep_rollbacker_thread
use test;
create table t1 (a int not null primary key) engine=innodb;
insert into t1 values (1),(2);
use performance_schema;
select name from mutex_instances where name like 'wait/synch/mutex/sql/LOCK_wsrep%' order by name;
name wait/synch/mutex/sql/LOCK_wsrep_config_state
name wait/synch/mutex/sql/LOCK_wsrep_desync
name wait/synch/mutex/sql/LOCK_wsrep_ready
name wait/synch/mutex/sql/LOCK_wsrep_replaying
name wait/synch/mutex/sql/LOCK_wsrep_rollback
name wait/synch/mutex/sql/LOCK_wsrep_slave_threads
name wait/synch/mutex/sql/LOCK_wsrep_sst
name wait/synch/mutex/sql/LOCK_wsrep_sst_init
select name from cond_instances where name like 'wait/synch/cond/sql/COND_wsrep%' order by name;
name wait/synch/cond/sql/COND_wsrep_ready
name wait/synch/cond/sql/COND_wsrep_replaying
name wait/synch/cond/sql/COND_wsrep_rollback
name wait/synch/cond/sql/COND_wsrep_sst
name wait/synch/cond/sql/COND_wsrep_sst_init
connection node_2;
use test;
SET SESSION wsrep_on=OFF;
CREATE TABLE t2 (f1 INTEGER) engine=innodb;
connection node_1;
use test;
CREATE TABLE t2 (f1 INTEGER) engine=innodb;
connection node_2;
SET SESSION wsrep_on=ON;
SELECT COUNT(*) FROM t1;
COUNT(*) 2
use performance_schema;
select count(*)>=1 from file_instances where file_name like '%GRA_%.log';
count(*)>=1 1
CALL mtr.add_suppression("Slave SQL: Error 'Table 't2' already exists' on query");
use test;
drop table t1;
drop table t2;

View file

@ -15,4 +15,4 @@
DROP PROCEDURE proc_update;
DROP TABLE t1, t2;
CALL mtr.add_suppression("conflict state 3 after post commit");
CALL mtr.add_suppression("conflict state ABORTED after post commit");

View file

@ -3,13 +3,17 @@
#
#
# Attempt to insert into t2 and check if insert actually inserted rows if
# a success was reported.
# test phase 1 is not deterministic
#
# Here we attempt to insert into t2 and check if insert actually
# inserted rows if a success was reported.
#
# However, deadlocks may or may not happen in this test execution
# it all depends on timing.
#
--source include/big_test.inc
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/big_test.inc
--source suite/galera/t/MW-328-header.inc
--connection node_2
@ -25,7 +29,7 @@ while ($count)
{
TRUNCATE TABLE t2;
--error 0,1213
--error 0,ER_LOCK_DEADLOCK
INSERT IGNORE INTO t2 SELECT f2 FROM t1;
if ($mysql_errno != 1213) {
--inc $successes
@ -44,14 +48,31 @@ while ($count)
--enable_query_log
#
# Check that the test produced both deadlocks and successes
#
--disable_query_log
--eval SELECT $successes > 0 AS have_successes
--eval SELECT $deadlocks > 0 AS have_deadlocks
--enable_query_log
--source suite/galera/t/MW-328-footer.inc
#
# Test phase 2 is deterministic
# Here we generate a sure conflict in node 1 and verify that
# insert failed in both nodes
#
--connection node_1
CREATE TABLE t1 (i int primary key, j int) engine=innodb;
INSERT INTO t1 values (1,0);
BEGIN;
UPDATE t1 SET j=1 WHERE i=1;
--connection node_2
UPDATE t1 SET j=2 WHERE i=1;
--connection node_1
--error ER_LOCK_DEADLOCK
COMMIT;
SELECT * FROM t1;
--connection node_2
SELECT * FROM t1;
--connection node_1
DROP TABLE t1;

View file

@ -7,9 +7,7 @@
# gets the deadlock error
#
--source include/big_test.inc
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source suite/galera/t/MW-328-header.inc
--connection node_2

View file

@ -7,9 +7,8 @@
# masks all deadlock errors
#
--source include/big_test.inc
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/big_test.inc
--source suite/galera/t/MW-328-header.inc
--connection node_2

View file

@ -7,7 +7,6 @@
#
--source include/galera_cluster.inc
--source include/have_innodb.inc
CREATE TABLE t1 (i INT) ENGINE = InnoDB;
INSERT INTO t1 (i) VALUES(1);

View file

@ -7,7 +7,6 @@
#
--source include/galera_cluster.inc
--source include/have_innodb.inc
create table t1 (i int primary key, j int) engine=innodb;
create table t2 (i int primary key, j int) engine=innodb;

View file

@ -0,0 +1,58 @@
#
# Test that wsrep mutexes, condition variables, files and
# threads are shown in performance schema
#
--source include/galera_cluster.inc
--source include/have_perfschema.inc
use performance_schema;
--vertical_results
--disable_ps_protocol
SELECT name
FROM threads
WHERE name LIKE 'thread/sql/wsrep%'
ORDER BY name;
--enable_ps_protocol
use test;
create table t1 (a int not null primary key) engine=innodb;
insert into t1 values (1),(2);
use performance_schema;
select name from mutex_instances where name like 'wait/synch/mutex/sql/LOCK_wsrep%' order by name;
select name from cond_instances where name like 'wait/synch/cond/sql/COND_wsrep%' order by name;
# Whenever a node fails to apply an event on a slave node, the database server creates a
# special binary log file of the event in the data directory. The naming convention the
# node uses for the filename is GRA_*.log.
# Thus, we need to produce a applier failure
--connection node_2
--exec rm -rf $MYSQLTEST_VARDIR/mysqld.2/data/GRA_*.log
# Create applier failure
use test;
SET SESSION wsrep_on=OFF;
CREATE TABLE t2 (f1 INTEGER) engine=innodb;
--connection node_1
use test;
CREATE TABLE t2 (f1 INTEGER) engine=innodb;
--connection node_2
SET SESSION wsrep_on=ON;
SELECT COUNT(*) FROM t1;
use performance_schema;
#
# Below we can't just count number of files as if you run this test more
# than once, test will create more files
#
select count(*)>=1 from file_instances where file_name like '%GRA_%.log';
CALL mtr.add_suppression("Slave SQL: Error 'Table 't2' already exists' on query");
use test;
drop table t1;
drop table t2;

View file

@ -4,17 +4,8 @@
# Not supported in embedded
-- source include/not_embedded.inc
# This test case needs to crash the server. Needs a debug server.
-- source include/have_debug.inc
# Don't test this under valgrind, memory leaks will occur.
-- source include/not_valgrind.inc
# Avoid CrashReporter popup on Mac
-- source include/not_crashrep.inc
-- source include/have_innodb.inc
-- source include/have_debug_sync.inc
# Create Insert Procedure
DELIMITER |;
@ -62,21 +53,11 @@ CALL populate_t1();
SELECT COUNT(*) FROM t1;
--enable_info
CREATE INDEX idx_title ON t1(title);
--disable_info
--source include/restart_mysqld.inc
CHECK TABLE t1;
SELECT * FROM t1 WHERE title = 'a10';
SELECT * FROM t1 WHERE title = 'a5000';
SELECT * FROM t1 WHERE title = 'a10000';
SELECT * FROM t1 WHERE title = 'a10010';
DROP TABLE t1;
RENAME TABLE t1 TO t0;
-- echo # Test Blob
@ -104,16 +85,32 @@ INSERT INTO t1 VALUES
SELECT CHAR_LENGTH(b) FROM t1;
ALTER TABLE t1 DROP COLUMN c;
--enable_info
ALTER TABLE t1 DROP COLUMN c, FORCE;
--disable_info
--source include/restart_mysqld.inc
CHECK TABLE t1;
CHECK TABLE t0,t1;
SELECT CHAR_LENGTH(b) FROM t1;
DROP TABLE t1;
RENAME TABLE t0 to t1;
CHECK TABLE t1;
SELECT * FROM t1 WHERE title = 'a10';
SELECT * FROM t1 WHERE title = 'a5000';
SELECT * FROM t1 WHERE title = 'a10000';
SELECT * FROM t1 WHERE title = 'a10010';
DROP TABLE t1;
# Test Crash Recovery
if ($row_format != 'COMPRESSED')
@ -140,17 +137,16 @@ if ($row_format == 'COMPRESSED')
CALL populate_t1();
-- enable_query_log
SET debug_dbug='+d,crash_commit_before';
# Write file to make mysql-test-run.pl start up the server again
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--error 2013
connect (hang,localhost,root);
SET DEBUG_SYNC='alter_table_inplace_trans_commit SIGNAL hung WAIT_FOR ever';
send
CREATE INDEX idx_title ON t1(title);
--enable_reconnect
--source include/wait_until_connected_again.inc
--disable_reconnect
connection default;
SET DEBUG_SYNC='now WAIT_FOR hung';
let $shutdown_timeout=0;
--source include/restart_mysqld.inc
disconnect hang;
SELECT COUNT(*) FROM t1;
@ -194,17 +190,16 @@ INSERT INTO t1 VALUES
SELECT CHAR_LENGTH(b) FROM t1;
SET debug_dbug='+d,crash_commit_before';
connect (hang,localhost,root);
SET DEBUG_SYNC='alter_table_inplace_trans_commit SIGNAL hung WAIT_FOR ever';
send
ALTER TABLE t1 DROP COLUMN c, FORCE;
# Write file to make mysql-test-run.pl start up the server again
--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--error 2013
ALTER TABLE t1 DROP COLUMN c;
--enable_reconnect
--source include/wait_until_connected_again.inc
--disable_reconnect
connection default;
SET DEBUG_SYNC='now WAIT_FOR hung';
--source include/restart_mysqld.inc
disconnect hang;
let $shutdown_timeout=60;
CHECK TABLE t1;
@ -212,10 +207,4 @@ SELECT CHAR_LENGTH(b) FROM t1;
DROP TABLE t1;
# Restore global variables
if ($row_format == 'COMPRESSED')
{
SET GLOBAL innodb_file_per_table=default;
}
DROP PROCEDURE populate_t1;

View file

@ -37,7 +37,9 @@ t1 CREATE TABLE `t1` (
FULLTEXT KEY `b_2` (`b`,`c`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
ALTER TABLE t1 FORCE, ALGORITHM=COPY;
SET DEBUG_DBUG='+d,crash_commit_before';
connect hang,localhost,root;
SET DEBUG_SYNC='alter_table_copy_trans_commit SIGNAL hung WAIT_FOR ever';
# create 32 secondary indexes
ALTER TABLE t ADD INDEX(b,c,d,a),ADD INDEX(b,c,a,d),ADD INDEX(b,a,c,d),ADD INDEX(b,a,d,c),
ADD INDEX(b,d,a,c),ADD INDEX(b,d,c,a),ADD INDEX(a,b,c,d),ADD INDEX(a,b,d,c),
ADD INDEX(a,c,b,d),ADD INDEX(a,c,d,b),ADD INDEX(a,d,b,c),ADD INDEX(a,d,c,b),
@ -47,7 +49,9 @@ ADD INDEX(d,b,a,c),ADD INDEX(d,b,c,a),ADD INDEX(d,c,a,b),ADD INDEX(d,c,b,a),
ADD INDEX(a,b,c), ADD INDEX(a,c,b), ADD INDEX(a,c,d), ADD INDEX(a,d,c),
ADD INDEX(a,b,d), ADD INDEX(a,d,b), ADD INDEX(b,c,d), ADD INDEX(b,d,c),
ALGORITHM=COPY;
ERROR HY000: Lost connection to MySQL server during query
connection default;
SET DEBUG_SYNC='now WAIT_FOR hung';
disconnect hang;
#sql-temporary.frm
#sql-temporary.ibd
FTS_INDEX_1.ibd

View file

@ -1,51 +0,0 @@
--- auto_increment_dup.result
+++ auto_increment_dup,skip-log-bin.reject
@@ -89,13 +89,14 @@
SET DEBUG_SYNC='execute_command_after_close_tables SIGNAL continue';
affected rows: 0
INSERT INTO t1(k) VALUES (2), (4), (5) ON DUPLICATE KEY UPDATE c='2';
-ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+affected rows: 3
+info: Records: 3 Duplicates: 0 Warnings: 0
connection con1;
#
# 2 duplicates
#
-affected rows: 3
-info: Records: 3 Duplicates: 0 Warnings: 0
+affected rows: 4
+info: Records: 3 Duplicates: 1 Warnings: 0
connection default;
#
# 3 rows
@@ -103,19 +104,21 @@
SELECT * FROM t1 order by k;
id k c
1 1 NULL
-2 2 NULL
-3 3 NULL
-affected rows: 3
+4 2 1
+2 3 NULL
+5 4 NULL
+6 5 NULL
+affected rows: 5
INSERT INTO t1(k) VALUES (2), (4), (5) ON DUPLICATE KEY UPDATE c='2';
-affected rows: 4
-info: Records: 3 Duplicates: 1 Warnings: 0
+affected rows: 6
+info: Records: 3 Duplicates: 3 Warnings: 0
SELECT * FROM t1 order by k;
id k c
1 1 NULL
-2 2 2
-3 3 NULL
-7 4 NULL
-8 5 NULL
+4 2 2
+2 3 NULL
+5 4 2
+6 5 2
affected rows: 5
disconnect con1;
disconnect con2;

View file

@ -89,13 +89,14 @@ affected rows: 0
SET DEBUG_SYNC='execute_command_after_close_tables SIGNAL continue';
affected rows: 0
INSERT INTO t1(k) VALUES (2), (4), (5) ON DUPLICATE KEY UPDATE c='2';
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
connection con1;
#
# 2 duplicates
#
affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
affected rows: 4
info: Records: 3 Duplicates: 1 Warnings: 0
connection default;
#
# 3 rows
@ -103,19 +104,21 @@ connection default;
SELECT * FROM t1 order by k;
id k c
1 1 NULL
2 2 NULL
3 3 NULL
affected rows: 3
4 2 1
2 3 NULL
5 4 NULL
6 5 NULL
affected rows: 5
INSERT INTO t1(k) VALUES (2), (4), (5) ON DUPLICATE KEY UPDATE c='2';
affected rows: 4
info: Records: 3 Duplicates: 1 Warnings: 0
affected rows: 6
info: Records: 3 Duplicates: 3 Warnings: 0
SELECT * FROM t1 order by k;
id k c
1 1 NULL
2 2 2
3 3 NULL
7 4 NULL
8 5 NULL
4 2 2
2 3 NULL
5 4 2
6 5 2
affected rows: 5
disconnect con1;
disconnect con2;

View file

@ -17,21 +17,9 @@ SELECT COUNT(*) FROM t1;
COUNT(*)
10000
CREATE INDEX idx_title ON t1(title);
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
SELECT * FROM t1 WHERE title = 'a10';
class id title
10 10 a10
SELECT * FROM t1 WHERE title = 'a5000';
class id title
5000 5000 a5000
SELECT * FROM t1 WHERE title = 'a10000';
class id title
10000 10000 a10000
SELECT * FROM t1 WHERE title = 'a10010';
class id title
DROP TABLE t1;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
RENAME TABLE t1 TO t0;
# Test Blob
CREATE TABLE t1(
a INT PRIMARY KEY,
@ -48,9 +36,12 @@ CHAR_LENGTH(b)
20000
40000
60000
ALTER TABLE t1 DROP COLUMN c;
CHECK TABLE t1;
ALTER TABLE t1 DROP COLUMN c, FORCE;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
CHECK TABLE t0,t1;
Table Op Msg_type Msg_text
test.t0 check status OK
test.t1 check status OK
SELECT CHAR_LENGTH(b) FROM t1;
CHAR_LENGTH(b)
@ -59,14 +50,33 @@ CHAR_LENGTH(b)
40000
60000
DROP TABLE t1;
RENAME TABLE t0 to t1;
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
SELECT * FROM t1 WHERE title = 'a10';
class id title
10 10 a10
SELECT * FROM t1 WHERE title = 'a5000';
class id title
5000 5000 a5000
SELECT * FROM t1 WHERE title = 'a10000';
class id title
10000 10000 a10000
SELECT * FROM t1 WHERE title = 'a10010';
class id title
DROP TABLE t1;
CREATE TABLE t1(
class INT,
id INT,
title VARCHAR(100)
) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
SET debug_dbug='+d,crash_commit_before';
connect hang,localhost,root;
SET DEBUG_SYNC='alter_table_inplace_trans_commit SIGNAL hung WAIT_FOR ever';
CREATE INDEX idx_title ON t1(title);
ERROR HY000: Lost connection to MySQL server during query
connection default;
SET DEBUG_SYNC='now WAIT_FOR hung';
disconnect hang;
SELECT COUNT(*) FROM t1;
COUNT(*)
10000
@ -104,9 +114,12 @@ CHAR_LENGTH(b)
20000
40000
60000
SET debug_dbug='+d,crash_commit_before';
ALTER TABLE t1 DROP COLUMN c;
ERROR HY000: Lost connection to MySQL server during query
connect hang,localhost,root;
SET DEBUG_SYNC='alter_table_inplace_trans_commit SIGNAL hung WAIT_FOR ever';
ALTER TABLE t1 DROP COLUMN c, FORCE;
connection default;
SET DEBUG_SYNC='now WAIT_FOR hung';
disconnect hang;
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
@ -137,21 +150,9 @@ SELECT COUNT(*) FROM t1;
COUNT(*)
10000
CREATE INDEX idx_title ON t1(title);
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
SELECT * FROM t1 WHERE title = 'a10';
class id title
10 10 a10
SELECT * FROM t1 WHERE title = 'a5000';
class id title
5000 5000 a5000
SELECT * FROM t1 WHERE title = 'a10000';
class id title
10000 10000 a10000
SELECT * FROM t1 WHERE title = 'a10010';
class id title
DROP TABLE t1;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
RENAME TABLE t1 TO t0;
# Test Blob
CREATE TABLE t1(
a INT PRIMARY KEY,
@ -168,9 +169,12 @@ CHAR_LENGTH(b)
20000
40000
60000
ALTER TABLE t1 DROP COLUMN c;
CHECK TABLE t1;
ALTER TABLE t1 DROP COLUMN c, FORCE;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
CHECK TABLE t0,t1;
Table Op Msg_type Msg_text
test.t0 check status OK
test.t1 check status OK
SELECT CHAR_LENGTH(b) FROM t1;
CHAR_LENGTH(b)
@ -179,14 +183,33 @@ CHAR_LENGTH(b)
40000
60000
DROP TABLE t1;
RENAME TABLE t0 to t1;
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
SELECT * FROM t1 WHERE title = 'a10';
class id title
10 10 a10
SELECT * FROM t1 WHERE title = 'a5000';
class id title
5000 5000 a5000
SELECT * FROM t1 WHERE title = 'a10000';
class id title
10000 10000 a10000
SELECT * FROM t1 WHERE title = 'a10010';
class id title
DROP TABLE t1;
CREATE TABLE t1(
class INT,
id INT,
title VARCHAR(100)
) ENGINE=InnoDB ROW_FORMAT=COMPACT;
SET debug_dbug='+d,crash_commit_before';
connect hang,localhost,root;
SET DEBUG_SYNC='alter_table_inplace_trans_commit SIGNAL hung WAIT_FOR ever';
CREATE INDEX idx_title ON t1(title);
ERROR HY000: Lost connection to MySQL server during query
connection default;
SET DEBUG_SYNC='now WAIT_FOR hung';
disconnect hang;
SELECT COUNT(*) FROM t1;
COUNT(*)
10000
@ -224,9 +247,12 @@ CHAR_LENGTH(b)
20000
40000
60000
SET debug_dbug='+d,crash_commit_before';
ALTER TABLE t1 DROP COLUMN c;
ERROR HY000: Lost connection to MySQL server during query
connect hang,localhost,root;
SET DEBUG_SYNC='alter_table_inplace_trans_commit SIGNAL hung WAIT_FOR ever';
ALTER TABLE t1 DROP COLUMN c, FORCE;
connection default;
SET DEBUG_SYNC='now WAIT_FOR hung';
disconnect hang;
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
@ -257,21 +283,9 @@ SELECT COUNT(*) FROM t1;
COUNT(*)
10000
CREATE INDEX idx_title ON t1(title);
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
SELECT * FROM t1 WHERE title = 'a10';
class id title
10 10 a10
SELECT * FROM t1 WHERE title = 'a5000';
class id title
5000 5000 a5000
SELECT * FROM t1 WHERE title = 'a10000';
class id title
10000 10000 a10000
SELECT * FROM t1 WHERE title = 'a10010';
class id title
DROP TABLE t1;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
RENAME TABLE t1 TO t0;
# Test Blob
CREATE TABLE t1(
a INT PRIMARY KEY,
@ -288,9 +302,12 @@ CHAR_LENGTH(b)
20000
40000
60000
ALTER TABLE t1 DROP COLUMN c;
CHECK TABLE t1;
ALTER TABLE t1 DROP COLUMN c, FORCE;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
CHECK TABLE t0,t1;
Table Op Msg_type Msg_text
test.t0 check status OK
test.t1 check status OK
SELECT CHAR_LENGTH(b) FROM t1;
CHAR_LENGTH(b)
@ -299,14 +316,33 @@ CHAR_LENGTH(b)
40000
60000
DROP TABLE t1;
RENAME TABLE t0 to t1;
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
SELECT * FROM t1 WHERE title = 'a10';
class id title
10 10 a10
SELECT * FROM t1 WHERE title = 'a5000';
class id title
5000 5000 a5000
SELECT * FROM t1 WHERE title = 'a10000';
class id title
10000 10000 a10000
SELECT * FROM t1 WHERE title = 'a10010';
class id title
DROP TABLE t1;
CREATE TABLE t1(
class INT,
id INT,
title VARCHAR(100)
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
SET debug_dbug='+d,crash_commit_before';
connect hang,localhost,root;
SET DEBUG_SYNC='alter_table_inplace_trans_commit SIGNAL hung WAIT_FOR ever';
CREATE INDEX idx_title ON t1(title);
ERROR HY000: Lost connection to MySQL server during query
connection default;
SET DEBUG_SYNC='now WAIT_FOR hung';
disconnect hang;
SELECT COUNT(*) FROM t1;
COUNT(*)
10000
@ -344,9 +380,12 @@ CHAR_LENGTH(b)
20000
40000
60000
SET debug_dbug='+d,crash_commit_before';
ALTER TABLE t1 DROP COLUMN c;
ERROR HY000: Lost connection to MySQL server during query
connect hang,localhost,root;
SET DEBUG_SYNC='alter_table_inplace_trans_commit SIGNAL hung WAIT_FOR ever';
ALTER TABLE t1 DROP COLUMN c, FORCE;
connection default;
SET DEBUG_SYNC='now WAIT_FOR hung';
disconnect hang;
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
@ -378,21 +417,9 @@ SELECT COUNT(*) FROM t1;
COUNT(*)
10000
CREATE INDEX idx_title ON t1(title);
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
SELECT * FROM t1 WHERE title = 'a10';
class id title
10 10 a10
SELECT * FROM t1 WHERE title = 'a5000';
class id title
5000 5000 a5000
SELECT * FROM t1 WHERE title = 'a10000';
class id title
10000 10000 a10000
SELECT * FROM t1 WHERE title = 'a10010';
class id title
DROP TABLE t1;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
RENAME TABLE t1 TO t0;
# Test Blob
SET GLOBAL innodb_file_per_table=1;
CREATE TABLE t1(
@ -410,9 +437,12 @@ CHAR_LENGTH(b)
20000
40000
60000
ALTER TABLE t1 DROP COLUMN c;
CHECK TABLE t1;
ALTER TABLE t1 DROP COLUMN c, FORCE;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
CHECK TABLE t0,t1;
Table Op Msg_type Msg_text
test.t0 check status OK
test.t1 check status OK
SELECT CHAR_LENGTH(b) FROM t1;
CHAR_LENGTH(b)
@ -421,15 +451,34 @@ CHAR_LENGTH(b)
40000
60000
DROP TABLE t1;
RENAME TABLE t0 to t1;
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
SELECT * FROM t1 WHERE title = 'a10';
class id title
10 10 a10
SELECT * FROM t1 WHERE title = 'a5000';
class id title
5000 5000 a5000
SELECT * FROM t1 WHERE title = 'a10000';
class id title
10000 10000 a10000
SELECT * FROM t1 WHERE title = 'a10010';
class id title
DROP TABLE t1;
SET GLOBAL innodb_file_per_table=1;
CREATE TABLE t1(
class INT,
id INT,
title VARCHAR(100)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4;
SET debug_dbug='+d,crash_commit_before';
connect hang,localhost,root;
SET DEBUG_SYNC='alter_table_inplace_trans_commit SIGNAL hung WAIT_FOR ever';
CREATE INDEX idx_title ON t1(title);
ERROR HY000: Lost connection to MySQL server during query
connection default;
SET DEBUG_SYNC='now WAIT_FOR hung';
disconnect hang;
SELECT COUNT(*) FROM t1;
COUNT(*)
10000
@ -468,9 +517,12 @@ CHAR_LENGTH(b)
20000
40000
60000
SET debug_dbug='+d,crash_commit_before';
ALTER TABLE t1 DROP COLUMN c;
ERROR HY000: Lost connection to MySQL server during query
connect hang,localhost,root;
SET DEBUG_SYNC='alter_table_inplace_trans_commit SIGNAL hung WAIT_FOR ever';
ALTER TABLE t1 DROP COLUMN c, FORCE;
connection default;
SET DEBUG_SYNC='now WAIT_FOR hung';
disconnect hang;
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
@ -481,5 +533,4 @@ CHAR_LENGTH(b)
40000
60000
DROP TABLE t1;
SET GLOBAL innodb_file_per_table=default;
DROP PROCEDURE populate_t1;

View file

@ -37,11 +37,11 @@ SELECT * FROM t1 WHERE MATCH(b,c) AGAINST ('column');
SHOW CREATE TABLE t1;
ALTER TABLE t1 FORCE, ALGORITHM=COPY;
# crash right after the last write_row(), before the first commit of ALTER TABLE
--source include/expect_crash.inc
# kill right after the last write_row(), before the first commit of ALTER TABLE
connect (hang,localhost,root);
SET DEBUG_DBUG='+d,crash_commit_before';
--error 2013
SET DEBUG_SYNC='alter_table_copy_trans_commit SIGNAL hung WAIT_FOR ever';
send
# create 32 secondary indexes
ALTER TABLE t ADD INDEX(b,c,d,a),ADD INDEX(b,c,a,d),ADD INDEX(b,a,c,d),ADD INDEX(b,a,d,c),
ADD INDEX(b,d,a,c),ADD INDEX(b,d,c,a),ADD INDEX(a,b,c,d),ADD INDEX(a,b,d,c),
@ -53,8 +53,13 @@ ALTER TABLE t ADD INDEX(b,c,d,a),ADD INDEX(b,c,a,d),ADD INDEX(b,a,c,d),ADD INDEX
ADD INDEX(a,b,d), ADD INDEX(a,d,b), ADD INDEX(b,c,d), ADD INDEX(b,d,c),
ALGORITHM=COPY;
connection default;
SET DEBUG_SYNC='now WAIT_FOR hung';
let $shutdown_timeout=0;
--let $restart_parameters= --innodb-force-recovery=3
--source include/start_mysqld.inc
--source include/restart_mysqld.inc
disconnect hang;
let $shutdown_timeout=;
let $datadir=`select @@datadir`;
--replace_regex /#sql-[0-9a-f_]*/#sql-temporary/ /FTS_[0-9a-f]*_[0-9a-f]*/FTS/
--list_files $datadir/test

View file

@ -8,8 +8,6 @@
--source include/have_debug_sync.inc
--source include/innodb_binlog.inc
let $stmt= `SELECT @@GLOBAL.log_bin`;
set global transaction isolation level repeatable read;
CREATE TABLE t1(
@ -84,13 +82,7 @@ SET DEBUG_SYNC='ha_write_row_end SIGNAL write_row_done WAIT_FOR continue';
--reap
SET DEBUG_SYNC='execute_command_after_close_tables SIGNAL continue';
if ($stmt) {
--error ER_LOCK_WAIT_TIMEOUT
INSERT INTO t1(k) VALUES (2), (4), (5) ON DUPLICATE KEY UPDATE c='2';
}
if (!$stmt) {
INSERT INTO t1(k) VALUES (2), (4), (5) ON DUPLICATE KEY UPDATE c='2';
}
--connection con1
--echo #

View file

@ -0,0 +1,30 @@
# Kill the server
CREATE TABLE t(i INT) ENGINE InnoDB;
INSERT INTO t VALUES
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
# xtrabackup backup, execute the following query after test.t is copied:
# BEGIN NOT ATOMIC INSERT INTO test.t SELECT * FROM test.t; UPDATE test.t SET i = 10 WHERE i = 0; DELETE FROM test.t WHERE i = 1; END
SELECT count(*) FROM t WHERE i = 0;
count(*)
0
# xtrabackup prepare
# shutdown server
# remove datadir
# xtrabackup move back
# restart server
SELECT count(*) FROM t WHERE i = 0;
count(*)
0
Ok
Ok
DROP TABLE t;
# Kill the server

View file

@ -0,0 +1,87 @@
# The general reason why innodb redo log file is limited by 512G is that
# log_block_convert_lsn_to_no() returns value limited by 1G. But there is no
# need to have unique log block numbers in log group. This test forces innodb
# to generate redo log files with non-unique log block numbers and tests
# recovery process with such numbers.
--source include/have_innodb.inc
--source include/have_debug.inc
--let MYSQLD_DATADIR= `select @@datadir`
let $MYSQLD_BOOTSTRAP_CMD= $MYSQLD_BOOTSTRAP_CMD --datadir=$MYSQLD_DATADIR --debug-dbug=+d,innodb_small_log_block_no_limit;
--source include/kill_mysqld.inc
--rmdir $MYSQLD_DATADIR
--mkdir $MYSQLD_DATADIR
--mkdir $MYSQLD_DATADIR/mysql
--mkdir $MYSQLD_DATADIR/test
--exec $MYSQLD_BOOTSTRAP_CMD < $MYSQL_BOOTSTRAP_SQL_FILE >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1
let $old_restart_parameters=$restart_parameters;
let $restart_parameters= $old_restart_parameters --debug-dbug=+d,innodb_small_log_block_no_limit;
--source include/start_mysqld.inc
CREATE TABLE t(i INT) ENGINE InnoDB;
INSERT INTO t VALUES
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9),
(0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
--let after_copy_test_t=BEGIN NOT ATOMIC INSERT INTO test.t SELECT * FROM test.t; UPDATE test.t SET i = 10 WHERE i = 0; DELETE FROM test.t WHERE i = 1; END
--echo # xtrabackup backup, execute the following query after test.t is copied:
--echo # $after_copy_test_t
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
--disable_result_log
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --dbug=+d,mariabackup_events,innodb_small_log_block_no_limit;
--enable_result_log
--let $total_before=`SELECT count(*) FROM t`
SELECT count(*) FROM t WHERE i = 0;
--let $updated_before=`SELECT count(*) FROM t WHERE i = 10`
echo # xtrabackup prepare;
--disable_result_log
exec $XTRABACKUP --prepare --target-dir=$targetdir --dbug=+d,innodb_small_log_block_no_limit;
--source include/restart_and_restore.inc
--enable_result_log
--let $total_after=`SELECT count(*) FROM t`
SELECT count(*) FROM t WHERE i = 0;
--let $updated_after=`SELECT count(*) FROM t WHERE i = 10`
if ($total_before == $total_after) {
--echo Ok
}
if ($total_before != $total_after) {
--echo Failed
}
if ($updated_before == $updated_after) {
--echo Ok
}
if ($updated_before != $updated_after) {
--echo Failed
}
DROP TABLE t;
rmdir $targetdir;
--source include/kill_mysqld.inc
--rmdir $MYSQLD_DATADIR
perl;
use lib "lib";
use My::File::Path;
my $install_db_dir = ($ENV{MTR_PARALLEL} == 1) ?
"$ENV{'MYSQLTEST_VARDIR'}/install.db" :
"$ENV{'MYSQLTEST_VARDIR'}/../install.db";
copytree($install_db_dir, $ENV{'MYSQLD_DATADIR'});
EOF
--let $restart_parameters= $old_restart_parameters
--source include/start_mysqld.inc

View file

@ -0,0 +1,20 @@
include/master-slave.inc
[connection master]
CREATE TEMPORARY TABLE t1 (a INT NOT NULL);
LOAD DATA INFILE 'x' INTO TABLE x;
ERROR 42S02: Table 'test.x' doesn't exist
CREATE OR REPLACE TEMPORARY TABLE t1 (x INT) PARTITION BY HASH(x);
ERROR HY000: Cannot create temporary table with partitions
"************** DROP TEMPORARY TABLE Should be present in Binary log **************"
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE t1 (a INT NOT NULL)
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; CREATE OR REPLACE TEMPORARY TABLE t1 (x INT) PARTITION BY HASH(x)
CREATE TABLE t1 (b INT);
INSERT INTO t1 VALUES (NULL);
connection slave;
connection master;
DROP TABLE t1;
include/rpl_end.inc

View file

@ -41,7 +41,7 @@ START SLAVE;
.. con='slave' warn='1' qlog='1' rlog='1' aborterr='1'
...==== BEGIN include/wait_for_slave_param.inc [Slave_IO_Running] ====
... con='slave' warn='1' qlog='1' rlog='1' aborterr='1'
Waiting until 'Slave_IO_Running' = 'Yes' [timeout='300', $slave_error_param='Last_IO_Errno']
Waiting until 'Slave_IO_Running' = 'Yes' [$slave_error_param='Last_IO_Errno']
[connection slave]
...==== END include/wait_for_slave_param.inc [Slave_IO_Running] ====
... con='slave' warn='1' qlog='1' rlog='1' aborterr='1'
@ -52,7 +52,7 @@ Waiting until 'Slave_IO_Running' = 'Yes' [timeout='300', $slave_error_param='Las
.. con='slave' warn='1' qlog='1' rlog='1' aborterr='1'
...==== BEGIN include/wait_for_slave_param.inc [Slave_SQL_Running] ====
... con='slave' warn='1' qlog='1' rlog='1' aborterr='1'
Waiting until 'Slave_SQL_Running' = 'Yes' [timeout='300', $slave_error_param='1']
Waiting until 'Slave_SQL_Running' = 'Yes' [$slave_error_param='1']
[connection slave]
...==== END include/wait_for_slave_param.inc [Slave_SQL_Running] ====
... con='slave' warn='1' qlog='1' rlog='1' aborterr='1'

View file

@ -1,31 +1,5 @@
call mtr.add_suppression("Unsafe statement written to the binary log using statement format");
include/master-slave.inc
[connection master]
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.");
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b INT,
UNIQUE(b));
connection slave;
connection master;
INSERT INTO t1(b) VALUES(1),(1),(2) ON DUPLICATE KEY UPDATE t1.b=10;
SELECT * FROM t1;
a b
1 10
2 2
connection slave;
call mtr.add_suppression("Slave SQL.*suffer.*http:..bugs.mysql.com.bug.php.id=24432");
include/wait_for_slave_sql_error.inc [errno=1105]
Last_SQL_Error = 'Error 'master may suffer from http://bugs.mysql.com/bug.php?id=24432 so slave stops; check error log on slave for more info' on query. Default database: 'test'. Query: 'INSERT INTO t1(b) VALUES(1),(1),(2) ON DUPLICATE KEY UPDATE t1.b=10''
SELECT * FROM t1;
a b
stop slave;
include/wait_for_slave_to_stop.inc
reset slave;
connection master;
reset master;
drop table t1;
connection slave;
start slave;
include/wait_for_slave_to_start.inc
connection master;
CREATE TABLE t1 (
id bigint(20) unsigned NOT NULL auto_increment,

View file

@ -0,0 +1,129 @@
include/master-slave.inc
[connection master]
call mtr.add_suppression("Unsafe statement written to the binary log using statement format");
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY , b INT,
UNIQUE(b), c int) engine=innodb;
connection slave;
connection master;
INSERT INTO t1 VALUES (1, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
connection master1;
INSERT INTO t1 VALUES(2, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
connection master;
COMMIT;
SELECT * FROM t1;
a b c
1 1 2
2 2 3
connection slave;
include/wait_for_slave_sql_error.inc [errno=1062]
Last_SQL_Error = 'Error 'Duplicate entry '1' for key 'b'' on query. Default database: 'test'. Query: 'INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c)''
#Different value from server
SELECT * FROM t1;
a b c
1 1 1
2 2 3
stop slave;
include/wait_for_slave_to_stop.inc
reset slave;
connection master;
reset master;
drop table t1;
connection slave;
start slave;
include/wait_for_slave_to_start.inc
connection master;
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT,
UNIQUE(b), c int) engine=innodb;
connection slave;
connection master;
INSERT INTO t1 VALUES (default, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (default, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
connection master1;
INSERT INTO t1 VALUES(default, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
connection master;
COMMIT;
SELECT * FROM t1;
a b c
1 1 2
3 2 3
connection slave;
#same data as master
SELECT * FROM t1;
a b c
1 1 2
3 2 3
connection master;
drop table t1;
connection slave;
connection master;
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT,
UNIQUE(b), c int, d int ) engine=innodb;
connection slave;
connection master;
INSERT INTO t1 VALUES (1, 1, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (2, NULL, 2, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
connection master1;
INSERT INTO t1 VALUES(3, NULL, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
connection master;
COMMIT;
SELECT * FROM t1;
a b c d
1 1 1 1
2 NULL 2 2
3 NULL 2 3
connection slave;
#same data as master
SELECT * FROM t1;
a b c d
1 1 1 1
2 NULL 2 2
3 NULL 2 3
connection master;
drop table t1;
connection slave;
connection master;
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT,
UNIQUE(b), c int) engine=innodb;
connection slave;
connection master;
INSERT INTO t1 VALUES (1, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
connection master1;
INSERT INTO t1 VALUES(2, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
connection master;
COMMIT;
SELECT * FROM t1;
a b c
1 1 2
2 2 3
connection slave;
include/wait_for_slave_sql_error.inc [errno=1062]
Last_SQL_Error = 'Error 'Duplicate entry '1' for key 'b'' on query. Default database: 'test'. Query: 'INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c)''
#Different value from server
SELECT * FROM t1;
a b c
1 1 1
2 2 3
stop slave;
include/wait_for_slave_to_stop.inc
reset slave;
connection master;
reset master;
drop table t1;
connection slave;
start slave;
include/wait_for_slave_to_start.inc
include/rpl_end.inc

View file

@ -0,0 +1,18 @@
include/master-slave.inc
[connection master]
connection slave;
SET @old_innodb_thread_concurrency := @@innodb_thread_concurrency;
SET @old_innodb_thread_sleep_delay := @@innodb_thread_sleep_delay;
SET GLOBAL innodb_thread_concurrency = 100;
connection master;
CREATE TABLE t(f INT) ENGINE=INNODB;
INSERT INTO t VALUES (10);
connection slave;
include/diff_tables.inc [master:t, slave:t]
"===== Clean up======="
connection master;
DROP TABLE t;
connection slave;
SET GLOBAL innodb_thread_concurrency = @old_innodb_thread_concurrency;
SET GLOBAL innodb_thread_sleep_delay = @old_innodb_thread_sleep_delay;
include/rpl_end.inc

View file

@ -1,5 +1,6 @@
include/master-slave.inc
[connection master]
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
CREATE TABLE t1(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB;
CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB;
CREATE TRIGGER trig1 AFTER INSERT ON t1
@ -49,9 +50,13 @@ connection master;
DROP TABLE t1;
CREATE TABLE t1(i INT, j INT, UNIQUE KEY(i), UNIQUE KEY(j)) ENGINE=INNODB;
INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1;
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
START TRANSACTION;
LOCK TABLES t1 WRITE;
INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1;
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
UNLOCK TABLES;
COMMIT;
connection slave;

View file

@ -0,0 +1,56 @@
# ==== Purpose ====
#
# Test verifies that failed CREATE OR REPLACE TEMPORARY TABLE statement which
# dropped the table but failed at a later stage of creation of temporary table
# is written to binarylog in row based replication.
#
# ==== Implementation ====
#
# Steps:
# 0 - Have mixed based replication mode.
# 1 - Create a temporary table. It will be replicated as mixed replication
# mode is in use.
# 2 - Execute an unsafe statement which will switch current statement
# binlog format to 'ROW'. i.e If binlog_format=MIXED, there are open
# temporary tables, and an unsafe statement is executed, then subsequent
# statements are logged in row format.
# 3 - Execute a CREATE OR REPLACE TEMPORARY TABLE statement which tries to
# create partitions on temporary table. Since it is not supported it will
# fail.
# 4 - Check the binary log output to ensure that the failed statement is
# written to the binary log.
# 5 - Slave should be up and running and in sync with master.
#
# ==== References ====
#
# MDEV-18930: Failed CREATE OR REPLACE TEMPORARY not written into binary log
# makes data on master and slave diverge
#
--source include/have_partition.inc
--source include/have_binlog_format_mixed.inc
--source include/master-slave.inc
CREATE TEMPORARY TABLE t1 (a INT NOT NULL);
# Execute an unsafe statement which switches replication mode internally from
# "STATEMENT" to "ROW".
--error ER_NO_SUCH_TABLE
LOAD DATA INFILE 'x' INTO TABLE x;
--error ER_PARTITION_NO_TEMPORARY
CREATE OR REPLACE TEMPORARY TABLE t1 (x INT) PARTITION BY HASH(x);
--echo "************** DROP TEMPORARY TABLE Should be present in Binary log **************"
--source include/show_binlog_events.inc
CREATE TABLE t1 (b INT);
INSERT INTO t1 VALUES (NULL);
--sync_slave_with_master
# Cleanup
--connection master
DROP TABLE t1;
--source include/rpl_end.inc

View file

@ -14,45 +14,6 @@ source include/have_binlog_checksum_off.inc;
source include/master-slave.inc;
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.");
#
# This is to test that slave properly detects if
# master may suffer from:
# BUG#24432 "INSERT... ON DUPLICATE KEY UPDATE skips auto_increment values"
# (i.e. on master, INSERT ON DUPLICATE KEY UPDATE is used and manipulates
# an auto_increment column, and is binlogged statement-based).
#
# testcase with INSERT VALUES
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b INT,
UNIQUE(b));
sync_slave_with_master;
connection master;
INSERT INTO t1(b) VALUES(1),(1),(2) ON DUPLICATE KEY UPDATE t1.b=10;
SELECT * FROM t1;
connection slave;
# show the error message
#1105 = ER_UNKNOWN_ERROR
--let $slave_sql_errno= 1105
--let $show_slave_sql_error= 1
call mtr.add_suppression("Slave SQL.*suffer.*http:..bugs.mysql.com.bug.php.id=24432");
--source include/wait_for_slave_sql_error.inc
# show that it was not replicated
SELECT * FROM t1;
# restart replication for the next testcase
stop slave;
--source include/wait_for_slave_to_stop.inc
reset slave;
connection master;
reset master;
drop table t1;
connection slave;
start slave;
--source include/wait_for_slave_to_start.inc
# testcase with INSERT SELECT
connection master;
CREATE TABLE t1 (

View file

@ -0,0 +1,121 @@
source include/have_debug.inc;
source include/have_innodb.inc;
-- source include/have_binlog_format_statement.inc
source include/master-slave.inc;
# MDEV-17614
# INSERT on dup key update is replication unsafe
# There can be three case
# 1. 2 unique key, Replication is unsafe.
# 2. 2 unique key , with one auto increment key, Safe to replicate because Innodb will acquire gap lock
# 3. n no of unique keys (n>1) but insert is only in 1 unique key
# 4. 2 unique key , with one auto increment key(but user gives auto inc value), unsafe to replicate
# Case 1
call mtr.add_suppression("Unsafe statement written to the binary log using statement format");
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY , b INT,
UNIQUE(b), c int) engine=innodb;
sync_slave_with_master;
connection master;
INSERT INTO t1 VALUES (1, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master1
INSERT INTO t1 VALUES(2, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master
COMMIT;
SELECT * FROM t1;
--connection slave
# show the error message
--let $slave_sql_errno= 1062
--let $show_slave_sql_error= 1
--source include/wait_for_slave_sql_error.inc
--echo #Different value from server
SELECT * FROM t1;
# restart replication for the next testcase
stop slave;
--source include/wait_for_slave_to_stop.inc
reset slave;
connection master;
reset master;
drop table t1;
connection slave;
start slave;
--source include/wait_for_slave_to_start.inc
# Case 2
--connection master
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT,
UNIQUE(b), c int) engine=innodb;
sync_slave_with_master;
connection master;
INSERT INTO t1 VALUES (default, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (default, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master1
INSERT INTO t1 VALUES(default, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master
COMMIT;
SELECT * FROM t1;
--sync_slave_with_master
--echo #same data as master
SELECT * FROM t1;
connection master;
drop table t1;
--sync_slave_with_master
# Case 3
--connection master
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT,
UNIQUE(b), c int, d int ) engine=innodb;
sync_slave_with_master;
connection master;
INSERT INTO t1 VALUES (1, 1, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (2, NULL, 2, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master1
INSERT INTO t1 VALUES(3, NULL, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master
COMMIT;
SELECT * FROM t1;
--sync_slave_with_master
--echo #same data as master
SELECT * FROM t1;
connection master;
drop table t1;
--sync_slave_with_master
# Case 4
--connection master
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT,
UNIQUE(b), c int) engine=innodb;
sync_slave_with_master;
connection master;
INSERT INTO t1 VALUES (1, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master1
INSERT INTO t1 VALUES(2, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master
COMMIT;
SELECT * FROM t1;
--connection slave
# show the error message
--let $slave_sql_errno= 1062
--let $show_slave_sql_error= 1
--source include/wait_for_slave_sql_error.inc
--echo #Different value from server
SELECT * FROM t1;
# restart replication for the next testcase
stop slave;
--source include/wait_for_slave_to_stop.inc
reset slave;
connection master;
reset master;
drop table t1;
connection slave;
start slave;
--source include/wait_for_slave_to_start.inc
--source include/rpl_end.inc

View file

@ -0,0 +1,41 @@
# ==== Purpose ====
#
# Test verifies that replication shouldn't hang when number of active threads
# on the slave server are less than the allowed innodb_thread_concurrency value.
#
# ==== Implementation ====
#
# Steps:
# 0 - Have master slave replication setup with engine being Innodb.
# 1 - Configure innodb_thread_concurrency = 100.
# 2 - Do some DML on master and sync the slave with master.
# 3 - Ensure replication doesn't hang.
#
# ==== References ====
#
# MDEV-20247: Replication hangs with "preparing" and never starts
#
--source include/master-slave.inc
--source include/have_innodb.inc
--connection slave
SET @old_innodb_thread_concurrency := @@innodb_thread_concurrency;
SET @old_innodb_thread_sleep_delay := @@innodb_thread_sleep_delay;
SET GLOBAL innodb_thread_concurrency = 100;
--connection master
CREATE TABLE t(f INT) ENGINE=INNODB;
INSERT INTO t VALUES (10);
--sync_slave_with_master
--let $diff_tables=master:t, slave:t
--source include/diff_tables.inc
--echo "===== Clean up======="
--connection master
DROP TABLE t;
--sync_slave_with_master
SET GLOBAL innodb_thread_concurrency = @old_innodb_thread_concurrency;
SET GLOBAL innodb_thread_sleep_delay = @old_innodb_thread_sleep_delay;
--source include/rpl_end.inc

View file

@ -24,7 +24,7 @@
--source include/have_innodb.inc
--source include/have_binlog_format_mixed.inc
--source include/master-slave.inc
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
# Case-1: BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS
# Statement is unsafe because it invokes a trigger or a
# stored function that inserts into an AUTO_INCREMENT column.

View file

@ -1473,7 +1473,7 @@ VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Size of each log file in a log group.
NUMERIC_MIN_VALUE 1048576
NUMERIC_MAX_VALUE 549755813888
NUMERIC_MAX_VALUE 17592186044415
NUMERIC_BLOCK_SIZE 65536
ENUM_VALUE_LIST NULL
READ_ONLY YES

View file

@ -1,18 +1,9 @@
SET @start_value = @@global.table_open_cache ;
SELECT @start_value;
@start_value
421
'#--------------------FN_DYNVARS_001_01------------------------#'
SET @@global.table_open_cache = 99;
SET @@global.table_open_cache = DeFAULT;
SELECT @@global.table_open_cache;
@@global.table_open_cache
2000
'#---------------------FN_DYNVARS_001_02-------------------------#'
SET @@global.table_open_cache = Default;
SELECT @@global.table_open_cache = 400;
@@global.table_open_cache = 400
0
SELECT @@global.table_open_cache > 0;
@@global.table_open_cache > 0
1
'#--------------------FN_DYNVARS_001_03------------------------#'
SET @@global.table_open_cache = 8;
Warnings:
@ -106,6 +97,3 @@ ERROR 42S02: Unknown table 'global' in field list
SELECT table_open_cache = @@session.table_open_cache ;
ERROR 42S22: Unknown column 'table_open_cache' in 'field list'
SET @@global.table_open_cache = @start_value;
SELECT @@global.table_open_cache ;
@@global.table_open_cache
421

View file

@ -4,8 +4,8 @@
# Scope: GLOBAL #
# Access Type: Dynamic #
# Data Type: numeric #
# Default Value: 400 #
# Range: 64-524288 #
# Default Value: 400 #
# Range: 64-524288 #
# #
# #
# Creation Date: 2008-02-13 #
@ -35,18 +35,6 @@
##########################################################################
SET @start_value = @@global.table_open_cache ;
SELECT @start_value;
--echo '#--------------------FN_DYNVARS_001_01------------------------#'
########################################################################
# Display the DEFAULT value of table_open_cache #
########################################################################
SET @@global.table_open_cache = 99;
SET @@global.table_open_cache = DeFAULT;
SELECT @@global.table_open_cache;
--echo '#---------------------FN_DYNVARS_001_02-------------------------#'
###############################################
@ -54,7 +42,7 @@ SELECT @@global.table_open_cache;
###############################################
SET @@global.table_open_cache = Default;
SELECT @@global.table_open_cache = 400;
SELECT @@global.table_open_cache > 0;
--echo '#--------------------FN_DYNVARS_001_03------------------------#'
########################################################################
@ -163,10 +151,7 @@ SELECT table_open_cache = @@session.table_open_cache ;
##############################
SET @@global.table_open_cache = @start_value;
SELECT @@global.table_open_cache ;
##################################################################
# END OF table_open_cache TESTS #
##################################################################

View file

@ -2864,7 +2864,8 @@ strncmpic(pcre_uint8 *s, pcre_uint8 *t, int n)
{
while (n--)
{
int c = tolower(*s++) - tolower(*t++);
int c = tolower(*s) - tolower(*t);
s++; t++;
if (c) return c;
}
return 0;

View file

@ -2434,6 +2434,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
KEY_PART *key_parts;
KEY *key_info;
PARAM param;
bool force_group_by = false;
if (check_stack_overrun(thd, 2*STACK_MIN_SIZE + sizeof(PARAM), buff))
DBUG_RETURN(0); // Fatal error flag is set
@ -2562,15 +2563,20 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
Try to construct a QUICK_GROUP_MIN_MAX_SELECT.
Notice that it can be constructed no matter if there is a range tree.
*/
DBUG_EXECUTE_IF("force_group_by", force_group_by = true; );
group_trp= get_best_group_min_max(&param, tree, best_read_time);
if (group_trp)
{
param.table->quick_condition_rows= MY_MIN(group_trp->records,
head->stat_records());
if (group_trp->read_cost < best_read_time)
if (group_trp->read_cost < best_read_time || force_group_by)
{
best_trp= group_trp;
best_read_time= best_trp->read_cost;
if (force_group_by)
{
goto force_plan;
}
}
}
@ -2670,6 +2676,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
}
}
force_plan:
thd->mem_root= param.old_root;
/* If we got a read plan, create a quick select from it. */
@ -11534,13 +11541,28 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length,
DBUG_ASSERT(cur_prefix != NULL);
result= file->ha_index_read_map(record, cur_prefix, keypart_map,
HA_READ_AFTER_KEY);
if (result || last_range->max_keypart_map == 0)
DBUG_RETURN(result);
key_range previous_endpoint;
last_range->make_max_endpoint(&previous_endpoint, prefix_length, keypart_map);
if (file->compare_key(&previous_endpoint) <= 0)
DBUG_RETURN(0);
if (result || last_range->max_keypart_map == 0) {
/*
Only return if actual failure occurred. For HA_ERR_KEY_NOT_FOUND
or HA_ERR_END_OF_FILE, we just want to continue to reach the next
set of ranges. It is possible for the storage engine to return
HA_ERR_KEY_NOT_FOUND/HA_ERR_END_OF_FILE even when there are more
keys if it respects the end range set by the read_range_first call
below.
*/
if (result != HA_ERR_KEY_NOT_FOUND && result != HA_ERR_END_OF_FILE)
DBUG_RETURN(result);
} else {
/*
For storage engines that don't respect end range, check if we've
moved past the current range.
*/
key_range previous_endpoint;
last_range->make_max_endpoint(&previous_endpoint, prefix_length,
keypart_map);
if (file->compare_key(&previous_endpoint) <= 0)
DBUG_RETURN(0);
}
}
uint count= ranges.elements - (uint)(cur_range - (QUICK_RANGE**) ranges.buffer);

View file

@ -4804,12 +4804,6 @@ extern "C" int thd_slave_thread(const MYSQL_THD thd)
}
extern "C" int thd_rpl_stmt_based(const MYSQL_THD thd)
{
return thd &&
!thd->is_current_stmt_binlog_format_row() &&
!thd->is_current_stmt_binlog_disabled();
}
/* Returns high resolution timestamp for the start
@ -6381,6 +6375,48 @@ int THD::decide_logging_format(TABLE_LIST *tables)
DBUG_RETURN(0);
}
int THD::decide_logging_format_low(TABLE *table)
{
/*
INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys
can be unsafe.
*/
if(wsrep_binlog_format() <= BINLOG_FORMAT_STMT &&
!is_current_stmt_binlog_format_row() &&
!lex->is_stmt_unsafe() &&
lex->sql_command == SQLCOM_INSERT &&
lex->duplicates == DUP_UPDATE)
{
uint unique_keys= 0;
uint keys= table->s->keys, i= 0;
Field *field;
for (KEY* keyinfo= table->s->key_info;
i < keys && unique_keys <= 1; i++, keyinfo++)
if (keyinfo->flags & HA_NOSAME &&
!(keyinfo->key_part->field->flags & AUTO_INCREMENT_FLAG &&
//User given auto inc can be unsafe
!keyinfo->key_part->field->val_int()))
{
for (uint j= 0; j < keyinfo->user_defined_key_parts; j++)
{
field= keyinfo->key_part[j].field;
if(!bitmap_is_set(table->write_set,field->field_index))
goto exit;
}
unique_keys++;
exit:;
}
if (unique_keys > 1)
{
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS);
binlog_unsafe_warning_flags|= lex->get_stmt_unsafe_flags();
set_current_stmt_binlog_format_row_if_mixed();
return 1;
}
}
return 0;
}
/*
Implementation of interface to write rows to the binary log through the

View file

@ -2452,6 +2452,20 @@ public:
/* container for handler's private per-connection data */
Ha_data ha_data[MAX_HA];
/**
Bit field for the state of binlog warnings.
The first Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types of
unsafeness that the current statement has.
This must be a member of THD and not of LEX, because warnings are
detected and issued in different places (@c
decide_logging_format() and @c binlog_query(), respectively).
Between these calls, the THD->lex object may change; e.g., if a
stored routine is invoked. Only THD persists between the calls.
*/
uint32 binlog_unsafe_warning_flags;
#ifndef MYSQL_CLIENT
binlog_cache_mngr * binlog_setup_trx_data();
@ -2561,20 +2575,6 @@ private:
*/
enum_binlog_format current_stmt_binlog_format;
/**
Bit field for the state of binlog warnings.
The first Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types of
unsafeness that the current statement has.
This must be a member of THD and not of LEX, because warnings are
detected and issued in different places (@c
decide_logging_format() and @c binlog_query(), respectively).
Between these calls, the THD->lex object may change; e.g., if a
stored routine is invoked. Only THD persists between the calls.
*/
uint32 binlog_unsafe_warning_flags;
/*
Number of outstanding table maps, i.e., table maps in the
transaction cache.
@ -4455,6 +4455,18 @@ public:
}
void leave_locked_tables_mode();
int decide_logging_format(TABLE_LIST *tables);
/*
In Some cases when decide_logging_format is called it does not have all
information to decide the logging format. So that cases we call decide_logging_format_2
at later stages in execution.
One example would be binlog format for IODKU but column with unique key is not inserted.
We dont have inserted columns info when we call decide_logging_format so on later stage we call
decide_logging_format_low
@returns 0 if no format is changed
1 if there is change in binlog format
*/
int decide_logging_format_low(TABLE *table);
enum need_invoker { INVOKER_NONE=0, INVOKER_USER, INVOKER_ROLE};
void binlog_invoker(bool role) { m_binlog_invoker= role ? INVOKER_ROLE : INVOKER_USER; }

View file

@ -1057,6 +1057,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
break;
}
thd->decide_logging_format_low(table);
#ifndef EMBEDDED_LIBRARY
if (lock_type == TL_WRITE_DELAYED)
{

View file

@ -6072,7 +6072,7 @@ finish:
trans_rollback_stmt(thd);
}
#ifdef WITH_WSREP
if (thd->spcont &&
else if (thd->spcont &&
(thd->wsrep_conflict_state == MUST_ABORT ||
thd->wsrep_conflict_state == ABORTED ||
thd->wsrep_conflict_state == CERT_FAILURE))

View file

@ -5219,7 +5219,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
err:
/* In RBR we don't need to log CREATE TEMPORARY TABLE */
if (thd->is_current_stmt_binlog_format_row() && create_info->tmp_table())
if (!result && thd->is_current_stmt_binlog_format_row() && create_info->tmp_table())
DBUG_RETURN(result);
if (create_info->tmp_table())
@ -10131,6 +10131,7 @@ end_temporary:
(ulong) (copied + deleted), (ulong) deleted,
(ulong) thd->get_stmt_da()->current_statement_warn_count());
my_ok(thd, copied + deleted, 0L, alter_ctx.tmp_buff);
DEBUG_SYNC(thd, "alter_table_inplace_trans_commit");
DBUG_RETURN(false);
err_new_table_cleanup:
@ -10232,12 +10233,14 @@ bool mysql_trans_commit_alter_copy_data(THD *thd)
uint save_unsafe_rollback_flags;
DBUG_ENTER("mysql_trans_commit_alter_copy_data");
/* Save flags as transcommit_implicit_are_deleting_them */
/* Save flags as trans_commit_implicit are deleting them */
save_unsafe_rollback_flags= thd->transaction.stmt.m_unsafe_rollback_flags;
DEBUG_SYNC(thd, "alter_table_copy_trans_commit");
if (ha_enable_transaction(thd, TRUE))
DBUG_RETURN(TRUE);
/*
Ensure that the new table is saved properly to disk before installing
the new .frm.

View file

@ -183,7 +183,19 @@ static PSI_file_info wsrep_files[]=
{
{ &key_file_wsrep_gra_log, "wsrep_gra_log", 0}
};
#endif
PSI_thread_key key_wsrep_sst_joiner, key_wsrep_sst_donor,
key_wsrep_rollbacker, key_wsrep_applier;
static PSI_thread_info wsrep_threads[]=
{
{&key_wsrep_sst_joiner, "wsrep_sst_joiner_thread", PSI_FLAG_GLOBAL},
{&key_wsrep_sst_donor, "wsrep_sst_donor_thread", PSI_FLAG_GLOBAL},
{&key_wsrep_rollbacker, "wsrep_rollbacker_thread", PSI_FLAG_GLOBAL},
{&key_wsrep_applier, "wsrep_applier_thread", PSI_FLAG_GLOBAL}
};
#endif /* HAVE_PSI_INTERFACE */
my_bool wsrep_inited = 0; // initialized ?
@ -799,6 +811,7 @@ void wsrep_thr_init()
mysql_mutex_register("sql", wsrep_mutexes, array_elements(wsrep_mutexes));
mysql_cond_register("sql", wsrep_conds, array_elements(wsrep_conds));
mysql_file_register("sql", wsrep_files, array_elements(wsrep_files));
mysql_thread_register("sql", wsrep_threads, array_elements(wsrep_threads));
#endif
mysql_mutex_init(key_LOCK_wsrep_ready, &LOCK_wsrep_ready, MY_MUTEX_INIT_FAST);
@ -814,6 +827,7 @@ void wsrep_thr_init()
mysql_mutex_init(key_LOCK_wsrep_slave_threads, &LOCK_wsrep_slave_threads, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_LOCK_wsrep_desync, &LOCK_wsrep_desync, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_LOCK_wsrep_config_state, &LOCK_wsrep_config_state, MY_MUTEX_INIT_FAST);
DBUG_VOID_RETURN;
}

View file

@ -286,7 +286,14 @@ extern PSI_mutex_key key_LOCK_wsrep_slave_threads;
extern PSI_mutex_key key_LOCK_wsrep_desync;
extern PSI_file_key key_file_wsrep_gra_log;
extern PSI_thread_key key_wsrep_sst_joiner;
extern PSI_thread_key key_wsrep_sst_donor;
extern PSI_thread_key key_wsrep_rollbacker;
extern PSI_thread_key key_wsrep_applier;
#endif /* HAVE_PSI_INTERFACE */
struct TABLE_LIST;
class Alter_info;
int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,

View file

@ -729,10 +729,10 @@ static ssize_t sst_prepare_other (const char* method,
pthread_t tmp;
sst_thread_arg arg(cmd_str(), env());
mysql_mutex_lock (&arg.lock);
ret = pthread_create (&tmp, NULL, sst_joiner_thread, &arg);
ret = mysql_thread_create (key_wsrep_sst_joiner, &tmp, NULL, sst_joiner_thread, &arg);
if (ret)
{
WSREP_ERROR("sst_prepare_other(): pthread_create() failed: %d (%s)",
WSREP_ERROR("sst_prepare_other(): mysql_thread_create() failed: %d (%s)",
ret, strerror(ret));
return -ret;
}
@ -1381,10 +1381,10 @@ static int sst_donate_other (const char* method,
pthread_t tmp;
sst_thread_arg arg(cmd_str(), env);
mysql_mutex_lock (&arg.lock);
ret = pthread_create (&tmp, NULL, sst_donor_thread, &arg);
ret = mysql_thread_create (key_wsrep_sst_donor, &tmp, NULL, sst_donor_thread, &arg);
if (ret)
{
WSREP_ERROR("sst_donate_other(): pthread_create() failed: %d (%s)",
WSREP_ERROR("sst_donate_other(): mysql_thread_create() failed: %d (%s)",
ret, strerror(ret));
return ret;
}

View file

@ -417,9 +417,26 @@ static void wsrep_replication_process(THD *thd)
static bool create_wsrep_THD(wsrep_thread_args* args)
{
ulong old_wsrep_running_threads= wsrep_running_threads;
mysql_mutex_lock(&LOCK_thread_count);
bool res= pthread_create(&args->thread_id, &connection_attrib, start_wsrep_THD,
ulong old_wsrep_running_threads= wsrep_running_threads;
#ifdef HAVE_PSI_THREAD_INTERFACE
PSI_thread_key key;
switch (args->thread_type)
{
case WSREP_APPLIER_THREAD:
key= key_wsrep_applier;
break;
case WSREP_ROLLBACKER_THREAD:
key= key_wsrep_rollbacker;
break;
default:
assert(0);
break;
}
#endif
bool res= mysql_thread_create(key, &args->thread_id, &connection_attrib, start_wsrep_THD,
(void*)args);
/*
if starting a thread on server startup, wait until the this thread's THD

View file

@ -879,7 +879,7 @@ MYSQL_FIELD *MYSQLC::GetNextField(void)
PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb)
{
PCSZ fmt;
char *name, v;
char *name, v= 0;
int n;
bool uns;
PCOLRES *pcrp, crp;

View file

@ -1708,9 +1708,9 @@ innobase_srv_conc_enter_innodb(
&& thd_is_replication_slave_thread(trx->mysql_thd)) {
const ulonglong end = my_interval_timer()
+ ulonglong(srv_replication_delay) * 1000000;
while (srv_conc_get_active_threads()
>= srv_thread_concurrency
|| my_interval_timer() >= end) {
while ((srv_conc_get_active_threads()
>= srv_thread_concurrency)
&& my_interval_timer() < end) {
os_thread_sleep(2000 /* 2 ms */);
}
} else {
@ -3925,14 +3925,12 @@ static int innodb_init_params()
DBUG_RETURN(HA_ERR_INITIALIZATION);
}
if (srv_n_log_files * srv_log_file_size
>= 512ULL * 1024ULL * 1024ULL * 1024ULL) {
/* log_block_convert_lsn_to_no() limits the returned block
number to 1G and given that OS_FILE_LOG_BLOCK_SIZE is 512
bytes, then we have a limit of 512 GB. If that limit is to
be raised, then log_block_convert_lsn_to_no() must be
modified. */
ib::error() << "Combined size of log files must be < 512 GB";
if (srv_n_log_files * srv_log_file_size >= log_group_max_size) {
/* Log group size is limited by the size of page number.
Remove this limitation when fil_io() is not used for
recovery log io. */
ib::error() << "Combined size of log files must be < "
<< log_group_max_size;
DBUG_RETURN(HA_ERR_INITIALIZATION);
}
@ -19591,7 +19589,7 @@ static MYSQL_SYSVAR_ULONG(log_buffer_size, srv_log_buffer_size,
static MYSQL_SYSVAR_ULONGLONG(log_file_size, srv_log_file_size,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Size of each log file in a log group.",
NULL, NULL, 48 << 20, 1 << 20, 512ULL << 30, UNIV_PAGE_SIZE_MAX);
NULL, NULL, 48 << 20, 1 << 20, log_group_max_size, UNIV_PAGE_SIZE_MAX);
/* OS_FILE_LOG_BLOCK_SIZE would be more appropriate than UNIV_PAGE_SIZE_MAX,
but fil_space_t is being used for the redo log, and it uses data pages. */

View file

@ -56,6 +56,9 @@ Smart ALTER TABLE
#include "row0sel.h"
#include "ha_innodb.h"
#include "ut0stage.h"
#include "span.h"
using st_::span;
static const char *MSG_UNSUPPORTED_ALTER_ONLINE_ON_VIRTUAL_COLUMN=
"INPLACE ADD or DROP of virtual columns cannot be "
@ -1636,20 +1639,22 @@ innobase_set_foreign_key_option(
/*******************************************************************//**
Check if a foreign key constraint can make use of an index
that is being created.
@param[in] col_names column names
@param[in] n_cols number of columns
@param[in] keys index information
@param[in] add indexes being created
@return useable index, or NULL if none found */
static MY_ATTRIBUTE((nonnull, warn_unused_result))
const KEY*
innobase_find_equiv_index(
/*======================*/
const char*const* col_names,
/*!< in: column names */
uint n_cols, /*!< in: number of columns */
const KEY* keys, /*!< in: index information */
const uint* add, /*!< in: indexes being created */
uint n_add) /*!< in: number of indexes to create */
uint n_cols,
const KEY* keys,
span<uint> add)
{
for (uint i = 0; i < n_add; i++) {
const KEY* key = &keys[add[i]];
for (span<uint>::iterator it = add.begin(), end = add.end(); it != end;
++it) {
const KEY* key = &keys[*it];
if (key->user_defined_key_parts < n_cols
|| key->flags & HA_SPATIAL) {
@ -1700,7 +1705,7 @@ no_match:
Find an index whose first fields are the columns in the array
in the same order and is not marked for deletion
@return matching index, NULL if not found */
static MY_ATTRIBUTE((nonnull(1,5), warn_unused_result))
static MY_ATTRIBUTE((nonnull(1,4), warn_unused_result))
dict_index_t*
innobase_find_fk_index(
/*===================*/
@ -1708,10 +1713,8 @@ innobase_find_fk_index(
const char** col_names,
/*!< in: column names, or NULL
to use table->col_names */
dict_index_t** drop_index,
span<dict_index_t*> drop_index,
/*!< in: indexes to be dropped */
ulint n_drop_index,
/*!< in: size of drop_index[] */
const char** columns,/*!< in: array of column names */
ulint n_cols) /*!< in: number of columns */
{
@ -1720,21 +1723,14 @@ innobase_find_fk_index(
index = dict_table_get_first_index(table);
while (index != NULL) {
if (dict_foreign_qualify_index(
table, col_names, columns, n_cols,
index, NULL, true, 0,
NULL, NULL, NULL)) {
for (ulint i = 0; i < n_drop_index; i++) {
if (index == drop_index[i]) {
/* Skip to-be-dropped indexes. */
goto next_rec;
}
}
return(index);
if (dict_foreign_qualify_index(table, col_names, columns,
n_cols, index, NULL, true, 0,
NULL, NULL, NULL)
&& std::find(drop_index.begin(), drop_index.end(), index)
== drop_index.end()) {
return index;
}
next_rec:
index = dict_table_get_next_index(index);
}
@ -1880,7 +1876,7 @@ innobase_get_foreign_key_info(
index = innobase_find_fk_index(
table, col_names,
drop_index, n_drop_index,
span<dict_index_t*>(drop_index, n_drop_index),
column_names, i);
/* MySQL would add a index in the creation
@ -1895,8 +1891,8 @@ innobase_get_foreign_key_info(
if (!index && !innobase_find_equiv_index(
column_names, static_cast<uint>(i),
ha_alter_info->key_info_buffer,
ha_alter_info->index_add_buffer,
ha_alter_info->index_add_count)) {
span<uint>(ha_alter_info->index_add_buffer,
ha_alter_info->index_add_count))) {
my_error(
ER_FK_NO_INDEX_CHILD,
MYF(0),
@ -5938,8 +5934,8 @@ innobase_check_foreign_key_index(
foreign->referenced_col_names,
foreign->n_fields,
ha_alter_info->key_info_buffer,
ha_alter_info->index_add_buffer,
ha_alter_info->index_add_count)) {
span<uint>(ha_alter_info->index_add_buffer,
ha_alter_info->index_add_count))) {
/* Index cannot be dropped. */
trx->error_info = index;
@ -5973,8 +5969,8 @@ innobase_check_foreign_key_index(
foreign->foreign_col_names,
foreign->n_fields,
ha_alter_info->key_info_buffer,
ha_alter_info->index_add_buffer,
ha_alter_info->index_add_count)) {
span<uint>(ha_alter_info->index_add_buffer,
ha_alter_info->index_add_count))) {
/* Index cannot be dropped. */
trx->error_info = index;

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation.
Copyright (c) 2017, 2019, MariaDB Corporation.
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

View file

@ -119,9 +119,6 @@ thd_is_replication_slave_thread(
/*============================*/
THD* thd); /*!< in: thread handle */
/** @return whether statement-based replication is active */
extern "C" int thd_rpl_stmt_based(const THD* thd);
/******************************************************************//**
Returns true if the transaction this thread is processing has edited
non-transactional tables. Used by the deadlock detector when deciding

View file

@ -40,6 +40,10 @@ Created 12/9/1995 Heikki Tuuri
#include "os0event.h"
#include "os0file.h"
#ifndef UINT32_MAX
#define UINT32_MAX (4294967295U)
#endif
/** Maximum number of srv_n_log_files, or innodb_log_files_in_group */
#define SRV_N_LOG_FILES_MAX 100
@ -493,6 +497,12 @@ Stored in LOG_HEADER_FORMAT. */
header */
#define LOG_FILE_HDR_SIZE (4 * OS_FILE_LOG_BLOCK_SIZE)
/* As long as fil_io() is used to handle log io, log group max size is limited
by (maximum page number) * (minimum page size). Page number type is uint32_t.
Remove this limitation if page number is no longer used for log file io. */
static const ulonglong log_group_max_size =
((ulonglong(UINT32_MAX) + 1) * UNIV_PAGE_SIZE_MIN - 1);
typedef ib_mutex_t LogSysMutex;
typedef ib_mutex_t FlushOrderMutex;

View file

@ -185,7 +185,9 @@ log_block_convert_lsn_to_no(
/*========================*/
lsn_t lsn) /*!< in: lsn of a byte within the block */
{
return(((ulint) (lsn / OS_FILE_LOG_BLOCK_SIZE) & 0x3FFFFFFFUL) + 1);
return(((ulint) (lsn / OS_FILE_LOG_BLOCK_SIZE) &
DBUG_EVALUATE_IF("innodb_small_log_block_no_limit",
0xFUL, 0x3FFFFFFFUL)) + 1);
}
/************************************************************//**

View file

@ -198,10 +198,6 @@ struct ins_node_t{
entry_list and sys fields are stored here;
if this is NULL, entry list should be created
and buffers for sys fields in row allocated */
dict_index_t* duplicate;
/* This is the first index that reported
DB_DUPLICATE_KEY. Used in the case of REPLACE
or INSERT ... ON DUPLICATE UPDATE. */
ulint magic_n;
};

View file

@ -0,0 +1,145 @@
/*****************************************************************************
Copyright (c) 2019, MariaDB Corporation.
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 Street, Fifth Floor, Boston, MA 02110-1335 USA
*****************************************************************************/
#pragma once
#include <cstddef>
#include <iterator>
namespace st_ {
template <class ElementType> class span {
public:
typedef ElementType element_type;
typedef ElementType value_type;
typedef size_t index_type;
typedef ptrdiff_t difference_type;
typedef element_type* pointer;
typedef const element_type* const_pointer;
typedef element_type& reference;
typedef const element_type& const_reference;
typedef pointer iterator;
typedef const pointer const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
span() : data_(NULL), size_(0) {}
span(pointer ptr, index_type count) : data_(ptr), size_(count) {}
span(pointer first, pointer last) : data_(first), size_(last - first) {}
template <size_t N> span(element_type (&arr)[N]) : data_(arr), size_(N)
{
}
template <class Container>
span(Container& cont) : data_(cont.begin()), size_(cont.size())
{
}
template <class Container>
span(const Container& cont) : data_(cont.begin()), size_(cont.size())
{
}
span(const span& other) : data_(other.data_), size_(other.size_) {}
~span(){};
span& operator=(const span& other)
{
data_ = other.data_;
size_ = other.size_;
return *this;
}
template <size_t Count> span<element_type> first() const
{
assert(!empty());
return span(data_, 1);
}
template <size_t Count> span<element_type> last() const
{
assert(!empty());
return span(data_ + size() - 1, 1);
}
span<element_type> first(index_type count) const
{
assert(!empty());
return span(data_, 1);
}
span<element_type> last(index_type count) const
{
assert(!empty());
return span(data_ + size() - 1, 1);
}
span<element_type> subspan(index_type offset, index_type count) const
{
assert(!empty());
assert(size() >= offset + count);
return span(data_ + offset, count);
}
index_type size() const { return size_; }
index_type size_bytes() const { return size_ * sizeof(ElementType); }
bool empty() const __attribute__((warn_unused_result))
{
return size_ == 0;
}
reference operator[](index_type idx) const
{
assert(size() > idx);
return data_[idx];
}
reference front() const
{
assert(!empty());
return data_[0];
}
reference back() const
{
assert(!empty());
return data_[size() - 1];
}
pointer data() const
{
assert(!empty());
return data_;
}
iterator begin() const { return data_; }
iterator end() const { return data_ + size_; }
reverse_iterator rbegin() const
{
return std::reverse_iterator<iterator>(std::advance(end(), -1));
}
reverse_iterator rend() const
{
return std::reverse_iterator<iterator>(
std::advance(begin(), -1));
}
private:
pointer data_;
index_type size_;
};
} // namespace st_

View file

@ -757,11 +757,14 @@ loop:
the trailer fields of the log blocks */
for (i = 0; i < write_len / OS_FILE_LOG_BLOCK_SIZE; i++) {
#ifdef UNIV_DEBUG
ulint hdr_no_2 = log_block_get_hdr_no(buf) + i;
DBUG_EXECUTE_IF("innodb_small_log_block_no_limit",
hdr_no_2 = ((hdr_no_2 - 1) & 0xFUL) + 1;);
#endif
ut_ad(pad_len >= len
|| i * OS_FILE_LOG_BLOCK_SIZE >= len - pad_len
|| log_block_get_hdr_no(
buf + i * OS_FILE_LOG_BLOCK_SIZE)
== log_block_get_hdr_no(buf) + i);
|| i * OS_FILE_LOG_BLOCK_SIZE >= len - pad_len
|| log_block_get_hdr_no(buf + i * OS_FILE_LOG_BLOCK_SIZE) == hdr_no_2);
log_block_store_checksum(buf + i * OS_FILE_LOG_BLOCK_SIZE);
}

View file

@ -684,11 +684,6 @@ que_thr_stop(
trx->lock.wait_thr = thr;
thr->state = QUE_THR_LOCK_WAIT;
} else if (trx->duplicates && trx->error_state == DB_DUPLICATE_KEY
&& thd_rpl_stmt_based(trx->mysql_thd)) {
return(FALSE);
} else if (trx->error_state != DB_SUCCESS
&& trx->error_state != DB_LOCK_WAIT) {

View file

@ -88,7 +88,6 @@ ins_node_create(
node->select = NULL;
node->trx_id = 0;
node->duplicate = NULL;
node->entry_sys_heap = mem_heap_create(128);
@ -193,7 +192,6 @@ ins_node_set_new_row(
node->state = INS_NODE_SET_IX_LOCK;
node->index = NULL;
node->entry = NULL;
node->duplicate = NULL;
node->row = row;
@ -2362,12 +2360,6 @@ row_ins_duplicate_error_in_clust(
true,
ULINT_UNDEFINED, &heap);
ulint lock_type =
trx->isolation_level <= TRX_ISO_READ_COMMITTED
|| (trx->mysql_thd
&& !thd_rpl_stmt_based(trx->mysql_thd))
? LOCK_REC_NOT_GAP : LOCK_ORDINARY;
/* We set a lock on the possible duplicate: this
is needed in logical logging of MySQL to make
sure that in roll-forward we get the same duplicate
@ -2384,13 +2376,13 @@ row_ins_duplicate_error_in_clust(
INSERT ON DUPLICATE KEY UPDATE). */
err = row_ins_set_exclusive_rec_lock(
lock_type,
LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor),
rec, cursor->index, offsets, thr);
} else {
err = row_ins_set_shared_rec_lock(
lock_type,
LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor), rec,
cursor->index, offsets, thr);
}
@ -2405,7 +2397,10 @@ row_ins_duplicate_error_in_clust(
if (row_ins_dupl_error_with_rec(
rec, entry, cursor->index, offsets)) {
goto duplicate;
duplicate:
trx->error_info = cursor->index;
err = DB_DUPLICATE_KEY;
goto func_exit;
}
}
}
@ -2448,10 +2443,7 @@ row_ins_duplicate_error_in_clust(
if (row_ins_dupl_error_with_rec(
rec, entry, cursor->index, offsets)) {
duplicate:
trx->error_info = cursor->index;
err = DB_DUPLICATE_KEY;
goto func_exit;
goto duplicate;
}
}
@ -3102,46 +3094,6 @@ row_ins_sec_index_entry_low(
&cursor, 0, __FILE__, __LINE__, &mtr);
}
if (!(flags & BTR_NO_LOCKING_FLAG)
&& dict_index_is_unique(index)
&& thr_get_trx(thr)->duplicates
&& thr_get_trx(thr)->isolation_level >= TRX_ISO_REPEATABLE_READ
&& thd_rpl_stmt_based(thr_get_trx(thr)->mysql_thd)) {
/* In statement-based replication, when replicating a
REPLACE statement or ON DUPLICATE KEY UPDATE clause, a
gap lock is taken on the position of the to-be-inserted record,
to avoid other concurrent transactions from inserting the same
record. */
dberr_t err;
const rec_t* rec = page_rec_get_next_const(
btr_cur_get_rec(&cursor));
ut_ad(!page_rec_is_infimum(rec));
offsets = rec_get_offsets(rec, index, offsets, true,
ULINT_UNDEFINED, &offsets_heap);
err = row_ins_set_exclusive_rec_lock(
LOCK_GAP, btr_cur_get_block(&cursor), rec,
index, offsets, thr);
switch (err) {
case DB_SUCCESS:
case DB_SUCCESS_LOCKED_REC:
if (thr_get_trx(thr)->error_state != DB_DUPLICATE_KEY) {
break;
}
/* Fall through (skip actual insert) after we have
successfully acquired the gap lock. */
default:
goto func_exit;
}
}
ut_ad(thr_get_trx(thr)->error_state == DB_SUCCESS);
if (dup_chk_only) {
goto func_exit;
}
@ -3664,13 +3616,6 @@ row_ins(
DBUG_PRINT("row_ins", ("table: %s", node->table->name.m_name));
trx_t* trx = thr_get_trx(thr);
if (node->duplicate) {
ut_ad(thd_rpl_stmt_based(trx->mysql_thd));
trx->error_state = DB_DUPLICATE_KEY;
}
if (node->state == INS_NODE_ALLOC_ROW_ID) {
row_ins_alloc_row_id_step(node);
@ -3696,91 +3641,7 @@ row_ins(
if (node->index->type != DICT_FTS) {
dberr_t err = row_ins_index_entry_step(node, thr);
switch (err) {
case DB_SUCCESS:
break;
case DB_NO_REFERENCED_ROW:
if (!dict_index_is_unique(node->index)) {
DBUG_RETURN(err);
}
/* fall through */
case DB_DUPLICATE_KEY:
ut_ad(dict_index_is_unique(node->index));
if (trx->isolation_level
>= TRX_ISO_REPEATABLE_READ
&& trx->duplicates
&& !node->table->is_temporary()
&& thd_rpl_stmt_based(trx->mysql_thd)) {
/* When we are in REPLACE statement or
INSERT .. ON DUPLICATE UPDATE
statement, we process all the
unique secondary indexes, even after we
encounter a duplicate error. This is
done to take necessary gap locks in
secondary indexes to block concurrent
transactions from inserting the
searched records. */
if (err == DB_NO_REFERENCED_ROW
&& node->duplicate) {
/* A foreign key check on a
unique index may fail to
find the record.
Consider as a example
following:
create table child(a int not null
primary key, b int not null,
c int,
unique key (b),
foreign key (b) references
parent (id)) engine=innodb;
insert into child values
(1,1,2);
insert into child(a) values
(1) on duplicate key update
c = 3;
Now primary key value 1
naturally causes duplicate
key error that will be
stored on node->duplicate.
If there was no duplicate
key error, we should return
the actual no referenced
row error.
As value for
column b used in both unique
key and foreign key is not
provided, server uses 0 as a
search value. This is
naturally, not found leading
to DB_NO_REFERENCED_ROW.
But, we should update the
row with primay key value 1
anyway.
Return the
original DB_DUPLICATE_KEY
error after
placing all gaplocks. */
err = DB_DUPLICATE_KEY;
break;
} else if (!node->duplicate) {
/* Save 1st dup error. Ignore
subsequent dup errors. */
node->duplicate = node->index;
trx->error_state
= DB_DUPLICATE_KEY;
}
break;
}
// fall through
default:
if (err != DB_SUCCESS) {
DBUG_RETURN(err);
}
}
@ -3797,31 +3658,13 @@ row_ins(
node->index = dict_table_get_next_index(node->index);
node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry);
}
/* After encountering a duplicate key error, we process
remaining indexes just to place gap locks and no actual
insertion will take place. These gap locks are needed
only for unique indexes. So skipping non-unique indexes. */
if (node->duplicate) {
ut_ad(thd_rpl_stmt_based(trx->mysql_thd));
while (node->index
&& !dict_index_is_unique(node->index)) {
node->index = dict_table_get_next_index(
node->index);
node->entry = UT_LIST_GET_NEXT(tuple_list,
node->entry);
}
trx->error_state = DB_DUPLICATE_KEY;
}
}
ut_ad(node->entry == NULL);
trx->error_info = node->duplicate;
node->state = INS_NODE_ALLOC_ROW_ID;
DBUG_RETURN(node->duplicate ? DB_DUPLICATE_KEY : DB_SUCCESS);
DBUG_RETURN(DB_SUCCESS);
}
/***********************************************************//**

View file

@ -1479,7 +1479,6 @@ error_exit:
goto run_again;
}
node->duplicate = NULL;
trx->op_info = "";
if (blob_heap != NULL) {
@ -1489,8 +1488,6 @@ error_exit:
return(err);
}
node->duplicate = NULL;
if (dict_table_has_fts_index(table)) {
doc_id_t doc_id;

View file

@ -1855,7 +1855,7 @@ dberr_t srv_start(bool create_new_db)
ut_a(fil_validate());
ut_a(log_space);
ut_a(srv_log_file_size <= 512ULL << 30);
ut_a(srv_log_file_size <= log_group_max_size);
const ulint size = 1 + ulint((srv_log_file_size - 1)
>> srv_page_size_shift);

View file

@ -1006,6 +1006,7 @@ static int maria_chk(HA_CHECK *param, char *filename)
int error,lock_type,recreate;
uint warning_printed_by_chk_status;
my_bool rep_quick= MY_TEST(param->testflag & (T_QUICK | T_FORCE_UNIQUENESS));
my_bool born_transactional;
MARIA_HA *info;
File datafile;
char llbuff[22],llbuff2[22];
@ -1448,6 +1449,7 @@ static int maria_chk(HA_CHECK *param, char *filename)
maria_lock_database(info, F_UNLCK);
end2:
born_transactional= share->base.born_transactional;
if (maria_close(info))
{
_ma_check_print_error(param, default_close_errmsg, my_errno, filename);
@ -1463,7 +1465,7 @@ end2:
MYF(MY_REDEL_MAKE_BACKUP) : MYF(0)));
}
if (opt_transaction_logging &&
share->base.born_transactional && !error &&
born_transactional && !error &&
(param->testflag & (T_REP_ANY | T_SORT_RECORDS | T_SORT_INDEX |
T_ZEROFILL)))
error= write_log_record(param);

View file

@ -683,7 +683,7 @@ static grn_rc
grn_ts_select_output(grn_ctx *ctx, grn_obj *table, grn_ts_str str,
const grn_ts_record *in, size_t n_in, size_t n_hits)
{
grn_ts_writer *writer;
grn_ts_writer *writer= 0;
grn_rc rc = grn_ts_writer_open(ctx, table, str, &writer);
if (rc != GRN_SUCCESS) {
return rc;

View file

@ -5173,7 +5173,7 @@ grn_ts_expr_node_deref(grn_ctx *ctx, grn_ts_expr_node **node_ptr)
{
grn_ts_expr_node *node = *node_ptr, **in_ptr = NULL;
while ((node->data_kind & ~GRN_TS_VECTOR_FLAG) == GRN_TS_REF) {
grn_ts_expr_node *new_node;
grn_ts_expr_node *new_node= 0;
grn_rc rc = grn_ts_expr_node_deref_once(ctx, node, &new_node);
if (rc != GRN_SUCCESS) {
if (in_ptr) {

View file

@ -14316,6 +14316,8 @@ static int rocksdb_validate_update_cf_options(
// then there's no point to proceed.
if (!Rdb_cf_options::parse_cf_options(str, &option_map)) {
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "rocksdb_update_cf_options", str);
// Free what we've copied with my_strdup above.
my_free((void*)(*(const char **)save));
return HA_EXIT_FAILURE;
}
// Loop through option_map and create missing column families

View file

@ -266,6 +266,17 @@ select a1, max(c) from t2 where a1 in ('a','b','d') group by a1,a2,b;
# B) Equalities only over the non-group 'B' attributes
# plans
--echo #
--echo # MariaDB: we dont have the following patch:
--echo #
--echo # commit 60a92a79a3b7fde3c6efe91799e344b977c8e5c3
--echo # Author: Manuel Ung <mung@fb.com>
--echo # Date: Thu Apr 19 23:06:27 2018 -0700
--echo #
--echo # Enhance group-by loose index scan
--echo #
--echo # So the following results are not very meaningful, but are still kept here
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
@ -730,9 +741,9 @@ explain extended select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,
explain extended select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;
# test multi_range_groupby flag
set optimizer_switch = 'multi_range_groupby=off';
#MariaDB: no support: set optimizer_switch = 'multi_range_groupby=off';
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'a' or b = 'b') group by a1;
set optimizer_switch = 'default';
#set optimizer_switch = 'default';
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'a' or b = 'b') group by a1;
@ -1361,41 +1372,41 @@ drop table t1;
eval CREATE TABLE t (a INT, b INT, KEY(a,b)) engine=$engine;
INSERT INTO t VALUES (1,1), (2,2), (3,3), (4,4), (1,0), (3,2), (4,5);
ANALYZE TABLE t;
let $DEFAULT_TRACE_MEM_SIZE=1048576; # 1MB
eval set optimizer_trace_max_mem_size=$DEFAULT_TRACE_MEM_SIZE;
set @@session.optimizer_trace='enabled=on';
set end_markers_in_json=on;
# MariaDB: 10.2 doesn't have trace, yet: let $DEFAULT_TRACE_MEM_SIZE=1048576; # 1MB
# eval set optimizer_trace_max_mem_size=$DEFAULT_TRACE_MEM_SIZE;
# set @@session.optimizer_trace='enabled=on';
# set end_markers_in_json=on;
ANALYZE TABLE t;
SELECT a, SUM(DISTINCT a), MIN(b) FROM t GROUP BY a;
EXPLAIN SELECT a, SUM(DISTINCT a), MIN(b) FROM t GROUP BY a;
SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
#SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
# FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
SELECT a, SUM(DISTINCT a), MAX(b) FROM t GROUP BY a;
EXPLAIN SELECT a, SUM(DISTINCT a), MAX(b) FROM t GROUP BY a;
SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
#SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
# FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
SELECT a, MAX(b) FROM t GROUP BY a HAVING SUM(DISTINCT a);
EXPLAIN SELECT a, MAX(b) FROM t GROUP BY a HAVING SUM(DISTINCT a);
SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
#SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
# FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
SELECT SUM(DISTINCT a), MIN(b), MAX(b) FROM t;
EXPLAIN SELECT SUM(DISTINCT a), MIN(b), MAX(b) FROM t;
SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
#SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
# FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
SELECT a, SUM(DISTINCT a), MIN(b), MAX(b) FROM t GROUP BY a;
EXPLAIN SELECT a, SUM(DISTINCT a), MIN(b), MAX(b) FROM t GROUP BY a;
SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
#SELECT TRACE RLIKE 'have_both_agg_distinct_and_min_max' AS OK
# FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
SET optimizer_trace_max_mem_size=DEFAULT;
SET optimizer_trace=DEFAULT;
SET end_markers_in_json=DEFAULT;
#SET optimizer_trace_max_mem_size=DEFAULT;
#SET optimizer_trace=DEFAULT;
#SET end_markers_in_json=DEFAULT;
DROP TABLE t;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,6 @@
CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=RocksDB;
LOCK TABLE t1 WRITE;
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
FLUSH TABLES;
ERROR HY000: MyRocks supports only READ COMMITTED and REPEATABLE READ isolation levels. Please change from current isolation level SERIALIZABLE
DROP TABLE t1;

View file

@ -1,8 +1,9 @@
--source include/have_debug.inc
set global debug="+d,force_group_by";
set @debug_tmp= @@debug_dbug;
set global debug_dbug="+d,force_group_by";
let $engine=RocksDB;
--source include/group_min_max.inc
set global debug="-d,force_group_by";
set global debug_dbug=@debug_tmp;

View file

@ -0,0 +1,9 @@
--source include/have_binlog_format_row.inc
--source include/have_rocksdb.inc
CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=RocksDB;
LOCK TABLE t1 WRITE;
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
--error ER_ISOLATION_MODE_NOT_SUPPORTED
FLUSH TABLES;
DROP TABLE t1;

View file

@ -1,4 +1,7 @@
--source include/have_rocksdb.inc
# MariaDB: including the below too many times causes really long argv list
# in win_main()'s argument which blows up some limit on Windows.
# Comment it out:
#--source include/have_rocksdb.inc
--source include/have_debug_sync.inc
--source include/count_sessions.inc

View file

@ -90,10 +90,10 @@ pthread_handler_t test_atomic_cas(void *arg)
y= my_atomic_load32(&bad);
x= (x*m+0x87654321) & INT_MAX32;
do {
ok= my_atomic_cas32(&bad, &y, (uint32)y+x);
ok= my_atomic_cas32((int32*) &bad, &y, y+x);
} while (!ok) ;
do {
ok= my_atomic_cas32(&bad, &y, y-x);
ok= my_atomic_cas32((int32*) &bad, &y, y-x);
} while (!ok) ;
}
return 0;