1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge 10.4 into 10.5

This commit is contained in:
Marko Mäkelä
2020-11-13 21:54:21 +02:00
53 changed files with 1633 additions and 478 deletions

View File

@@ -25,21 +25,24 @@
#define DBUG_ASSERT_IF_WSREP(A) DBUG_ASSERT(A) #define DBUG_ASSERT_IF_WSREP(A) DBUG_ASSERT(A)
#define WSREP_MYSQL_DB (char *)"mysql" #define WSREP_MYSQL_DB (char *)"mysql"
#define WSREP_TO_ISOLATION_BEGIN_IF(db_, table_, table_list_) \
if (WSREP_ON && WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_))
#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \ #define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \
if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) \ if (WSREP_ON && WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) \
goto wsrep_error_label; goto wsrep_error_label;
#define WSREP_TO_ISOLATION_BEGIN_CREATE(db_, table_, table_list_, create_info_) \ #define WSREP_TO_ISOLATION_BEGIN_CREATE(db_, table_, table_list_, create_info_) \
if (WSREP(thd) && \ if (WSREP_ON && WSREP(thd) && \
wsrep_to_isolation_begin(thd, db_, table_, \ wsrep_to_isolation_begin(thd, db_, table_, \
table_list_, NULL, create_info_)) \ table_list_, nullptr, nullptr, create_info_))\
goto wsrep_error_label; goto wsrep_error_label;
#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, create_info_) \ #define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, fk_tables_, create_info_) \
if (WSREP(thd) && wsrep_thd_is_local(thd) && \ if (WSREP(thd) && wsrep_thd_is_local(thd) && \
wsrep_to_isolation_begin(thd, db_, table_, \ wsrep_to_isolation_begin(thd, db_, table_, \
table_list_, alter_info_, create_info_)) \ table_list_, alter_info_, \
fk_tables_, create_info_)) \
goto wsrep_error_label; goto wsrep_error_label;
#define WSREP_TO_ISOLATION_END \ #define WSREP_TO_ISOLATION_END \
@@ -55,6 +58,10 @@
if (WSREP(thd) && !thd->lex->no_write_to_binlog \ if (WSREP(thd) && !thd->lex->no_write_to_binlog \
&& wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto wsrep_error_label; && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto wsrep_error_label;
#define WSREP_TO_ISOLATION_BEGIN_FK_TABLES(db_, table_, table_list_, fk_tables) \
if (WSREP(thd) && !thd->lex->no_write_to_binlog \
&& wsrep_to_isolation_begin(thd, db_, table_, table_list_, NULL, fk_tables))
#define WSREP_SYNC_WAIT(thd_, before_) \ #define WSREP_SYNC_WAIT(thd_, before_) \
{ if (WSREP_CLIENT(thd_) && \ { if (WSREP_CLIENT(thd_) && \
wsrep_sync_wait(thd_, before_)) goto wsrep_error_label; } wsrep_sync_wait(thd_, before_)) goto wsrep_error_label; }
@@ -68,7 +75,8 @@
#define WSREP_DEBUG(...) #define WSREP_DEBUG(...)
#define WSREP_ERROR(...) #define WSREP_ERROR(...)
#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) do { } while(0) #define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) do { } while(0)
#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, create_info_) #define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_, fk_tables_, create_info_)
#define WSREP_TO_ISOLATION_BEGIN_FK_TABLES(db_, table_, table_list_, fk_tables_)
#define WSREP_TO_ISOLATION_END #define WSREP_TO_ISOLATION_END
#define WSREP_TO_ISOLATION_BEGIN_CREATE(db_, table_, table_list_, create_info_) #define WSREP_TO_ISOLATION_BEGIN_CREATE(db_, table_, table_list_, create_info_)
#define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_) #define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_)

View File

@@ -130,5 +130,42 @@ connection default;
# #
alter user user1@localhost account lock; alter user user1@localhost account lock;
ERROR HY000: Access denied, this account is locked ERROR HY000: Access denied, this account is locked
#
# MDEV-24098 SHOW CREATE USER invalid for both PASSWORD EXPIRE and
# and LOCKED
#
alter user user1@localhost PASSWORD EXPIRE;
show create user user1@localhost;
CREATE USER for user1@localhost
CREATE USER `user1`@`localhost` ACCOUNT LOCK PASSWORD EXPIRE
drop user user1@localhost;
#
# MDEV-24098 CREATE USER/ALTER USER PASSWORD EXPIRE/LOCK in
# either order.
#
create user user1@localhost PASSWORD EXPIRE ACCOUNT LOCK;
show create user user1@localhost;
CREATE USER for user1@localhost
CREATE USER `user1`@`localhost` ACCOUNT LOCK PASSWORD EXPIRE
drop user user1@localhost;
create user user1@localhost ACCOUNT LOCK PASSWORD EXPIRE;
show create user user1@localhost;
CREATE USER for user1@localhost
CREATE USER `user1`@`localhost` ACCOUNT LOCK PASSWORD EXPIRE
alter user user1@localhost PASSWORD EXPIRE NEVER ACCOUNT UNLOCK ;
show create user user1@localhost;
CREATE USER for user1@localhost
CREATE USER `user1`@`localhost` PASSWORD EXPIRE
alter user user1@localhost ACCOUNT LOCK PASSWORD EXPIRE DEFAULT;
show create user user1@localhost;
CREATE USER for user1@localhost
CREATE USER `user1`@`localhost` ACCOUNT LOCK PASSWORD EXPIRE
alter user user1@localhost PASSWORD EXPIRE INTERVAL 60 DAY ACCOUNT UNLOCK;
select * from mysql.global_priv where user='user1';
Host User Priv
localhost user1 {"access":0,"version_id":100509,"plugin":"mysql_native_password","authentication_string":"","account_locked":false,"password_last_changed":0,"password_lifetime":60}
show create user user1@localhost;
CREATE USER for user1@localhost
CREATE USER `user1`@`localhost` PASSWORD EXPIRE
drop user user1@localhost; drop user user1@localhost;
drop user user2@localhost; drop user user2@localhost;

View File

@@ -137,6 +137,32 @@ alter user user1@localhost account lock;
--error ER_ACCOUNT_HAS_BEEN_LOCKED --error ER_ACCOUNT_HAS_BEEN_LOCKED
--change_user user1 --change_user user1
--echo #
--echo # MDEV-24098 SHOW CREATE USER invalid for both PASSWORD EXPIRE and
--echo # and LOCKED
--echo #
alter user user1@localhost PASSWORD EXPIRE;
show create user user1@localhost;
drop user user1@localhost;
--echo #
--echo # MDEV-24098 CREATE USER/ALTER USER PASSWORD EXPIRE/LOCK in
--echo # either order.
--echo #
create user user1@localhost PASSWORD EXPIRE ACCOUNT LOCK;
show create user user1@localhost;
drop user user1@localhost;
create user user1@localhost ACCOUNT LOCK PASSWORD EXPIRE;
show create user user1@localhost;
alter user user1@localhost PASSWORD EXPIRE NEVER ACCOUNT UNLOCK ;
show create user user1@localhost;
alter user user1@localhost ACCOUNT LOCK PASSWORD EXPIRE DEFAULT;
show create user user1@localhost;
# note output needs to be corrected by MDEV-24114: password expire users cannot be unexpired
alter user user1@localhost PASSWORD EXPIRE INTERVAL 60 DAY ACCOUNT UNLOCK;
select * from mysql.global_priv where user='user1';
show create user user1@localhost;
drop user user1@localhost; drop user user1@localhost;
drop user user2@localhost; drop user user2@localhost;

View File

@@ -647,6 +647,7 @@ sub run_test_server ($$$) {
# Client disconnected # Client disconnected
mtr_verbose("Child closed socket"); mtr_verbose("Child closed socket");
$s->remove($sock); $s->remove($sock);
$sock->close;
if (--$childs == 0){ if (--$childs == 0){
return ("Completed", $test_failure, $completed, $extra_warnings); return ("Completed", $test_failure, $completed, $extra_warnings);
} }
@@ -816,6 +817,7 @@ sub run_test_server ($$$) {
# Test failure due to warnings, force is off # Test failure due to warnings, force is off
return ("Warnings in log", 1, $completed, $extra_warnings); return ("Warnings in log", 1, $completed, $extra_warnings);
} }
next;
} }
elsif ($line =~ /^SPENT/) { elsif ($line =~ /^SPENT/) {
add_total_times($line); add_total_times($line);
@@ -4102,6 +4104,7 @@ sub run_testcase ($$) {
if (start_servers($tinfo)) if (start_servers($tinfo))
{ {
report_failure_and_restart($tinfo); report_failure_and_restart($tinfo);
unlink $path_current_testlog;
return 1; return 1;
} }
} }

View File

@@ -0,0 +1,8 @@
connection node_2;
connection node_1;
connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connection node_2a;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
connection node_2;
SET GLOBAL wsrep_on=OFF;
DROP TABLE t1;

View File

@@ -0,0 +1,657 @@
connection node_2;
connection node_1;
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1a;
SET SESSION wsrep_sync_wait=0;
connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1b;
SET SESSION wsrep_sync_wait=0;
######################################################################
# Test for OPTIMIZE
######################################################################
######################################################################
#
# Scenario #1: DML working on FK parent table BF aborted by DDL
# over child table
#
######################################################################
connection node_1;
SET SESSION wsrep_sync_wait=0;
CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
INSERT INTO p2 VALUES (1, 'INITIAL VALUE');
INSERT INTO p2 VALUES (2, 'INITIAL VALUE');
CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
INSERT INTO c1 VALUES (1,1);
CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk));
INSERT INTO c2 VALUES (1,1,1), (2,1,2);
connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
connection node_2;
SET SESSION wsrep_sync_wait=0;
OPTIMIZE TABLE c1 ;
Table Op Msg_type Msg_text
test.c1 optimize note Table does not support optimize, doing recreate + analyze instead
test.c1 optimize status OK
connection node_1;
COMMIT;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
connection node_2;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
######################################################################
#
# Scenario #2: DML working on FK parent table tries to replicate, but
# fails in certification for earlier DDL on child table
#
######################################################################
connection node_1;
BEGIN;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
OPTIMIZE TABLE c1 ;
Table Op Msg_type Msg_text
test.c1 optimize note Table does not support optimize, doing recreate + analyze instead
test.c1 optimize status OK
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
COMMIT;
connection node_1a;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT 'I deadlocked';
I deadlocked
I deadlocked
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
connection node_2;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
######################################################################
#
# Scenario #3: 2 DMLs working on two FK parent tables try to replicate,
# but fails in certification for earlier DDL on child table
# which is child to both FK parents
#
######################################################################
connection node_1;
BEGIN;
connection node_1b;
BEGIN;
connection node_1a;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
OPTIMIZE TABLE c2 ;
Table Op Msg_type Msg_text
test.c2 optimize note Table does not support optimize, doing recreate + analyze instead
test.c2 optimize status OK
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
COMMIT;
connection node_1b;
UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2;
COMMIT;
connection node_1a;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT 'I deadlocked';
I deadlocked
I deadlocked
connection node_1b;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT 'I deadlocked';
I deadlocked
I deadlocked
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
connection node_2;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
DROP TABLE c1, c2;
DROP TABLE p1, p2;
######################################################################
# Test for OPTIMIZE
######################################################################
connection node_1;
SET SESSION wsrep_sync_wait=0;
CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
INSERT INTO c1 VALUES (1,1);
######################################################################
#
# Scenario #4: DML working on FK parent table tries to replicate, but
# fails in certification for earlier DDL on child table
# and another temporary table. TMP table should be skipped
# but FK child table should be replicated with proper keys
#
######################################################################
connection node_1;
BEGIN;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
CREATE TEMPORARY TABLE tmp (i int);
OPTIMIZE TABLE c1, tmp ;
Table Op Msg_type Msg_text
test.c1 optimize note Table does not support optimize, doing recreate + analyze instead
test.c1 optimize status OK
test.tmp optimize note Table does not support optimize, doing recreate + analyze instead
test.tmp optimize status OK
DROP TABLE tmp;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
COMMIT;
connection node_1a;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT 'I deadlocked';
I deadlocked
I deadlocked
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
connection node_2;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
DROP TABLE c1;
DROP TABLE p1;
######################################################################
# Test for REPAIR
######################################################################
######################################################################
#
# Scenario #1: DML working on FK parent table BF aborted by DDL
# over child table
#
######################################################################
connection node_1;
SET SESSION wsrep_sync_wait=0;
CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
INSERT INTO p2 VALUES (1, 'INITIAL VALUE');
INSERT INTO p2 VALUES (2, 'INITIAL VALUE');
CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
INSERT INTO c1 VALUES (1,1);
CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk));
INSERT INTO c2 VALUES (1,1,1), (2,1,2);
connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
connection node_2;
SET SESSION wsrep_sync_wait=0;
REPAIR TABLE c1 ;
Table Op Msg_type Msg_text
test.c1 repair note The storage engine for the table doesn't support repair
connection node_1;
COMMIT;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
connection node_2;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
######################################################################
#
# Scenario #2: DML working on FK parent table tries to replicate, but
# fails in certification for earlier DDL on child table
#
######################################################################
connection node_1;
BEGIN;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
REPAIR TABLE c1 ;
Table Op Msg_type Msg_text
test.c1 repair note The storage engine for the table doesn't support repair
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
COMMIT;
connection node_1a;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT 'I deadlocked';
I deadlocked
I deadlocked
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
connection node_2;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
######################################################################
#
# Scenario #3: 2 DMLs working on two FK parent tables try to replicate,
# but fails in certification for earlier DDL on child table
# which is child to both FK parents
#
######################################################################
connection node_1;
BEGIN;
connection node_1b;
BEGIN;
connection node_1a;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
REPAIR TABLE c2 ;
Table Op Msg_type Msg_text
test.c2 repair note The storage engine for the table doesn't support repair
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
COMMIT;
connection node_1b;
UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2;
COMMIT;
connection node_1a;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT 'I deadlocked';
I deadlocked
I deadlocked
connection node_1b;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT 'I deadlocked';
I deadlocked
I deadlocked
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
connection node_2;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
DROP TABLE c1, c2;
DROP TABLE p1, p2;
######################################################################
# Test for REPAIR
######################################################################
connection node_1;
SET SESSION wsrep_sync_wait=0;
CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
INSERT INTO c1 VALUES (1,1);
######################################################################
#
# Scenario #4: DML working on FK parent table tries to replicate, but
# fails in certification for earlier DDL on child table
# and another temporary table. TMP table should be skipped
# but FK child table should be replicated with proper keys
#
######################################################################
connection node_1;
BEGIN;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
CREATE TEMPORARY TABLE tmp (i int);
REPAIR TABLE c1, tmp ;
Table Op Msg_type Msg_text
test.c1 repair note The storage engine for the table doesn't support repair
test.tmp repair note The storage engine for the table doesn't support repair
DROP TABLE tmp;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
COMMIT;
connection node_1a;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT 'I deadlocked';
I deadlocked
I deadlocked
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
connection node_2;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
DROP TABLE c1;
DROP TABLE p1;
######################################################################
# Test for ALTER ENGINE=INNODB
######################################################################
######################################################################
#
# Scenario #1: DML working on FK parent table BF aborted by DDL
# over child table
#
######################################################################
connection node_1;
SET SESSION wsrep_sync_wait=0;
CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
INSERT INTO p2 VALUES (1, 'INITIAL VALUE');
INSERT INTO p2 VALUES (2, 'INITIAL VALUE');
CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
INSERT INTO c1 VALUES (1,1);
CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk));
INSERT INTO c2 VALUES (1,1,1), (2,1,2);
connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
connection node_2;
SET SESSION wsrep_sync_wait=0;
ALTER TABLE c1 ENGINE=INNODB;
connection node_1;
COMMIT;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
connection node_2;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
######################################################################
#
# Scenario #2: DML working on FK parent table tries to replicate, but
# fails in certification for earlier DDL on child table
#
######################################################################
connection node_1;
BEGIN;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
ALTER TABLE c1 ENGINE=INNODB;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
COMMIT;
connection node_1a;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT 'I deadlocked';
I deadlocked
I deadlocked
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
connection node_2;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
######################################################################
#
# Scenario #3: 2 DMLs working on two FK parent tables try to replicate,
# but fails in certification for earlier DDL on child table
# which is child to both FK parents
#
######################################################################
connection node_1;
BEGIN;
connection node_1b;
BEGIN;
connection node_1a;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
ALTER TABLE c2 ENGINE=INNODB;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
COMMIT;
connection node_1b;
UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2;
COMMIT;
connection node_1a;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT 'I deadlocked';
I deadlocked
I deadlocked
connection node_1b;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT 'I deadlocked';
I deadlocked
I deadlocked
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
connection node_2;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
DROP TABLE c1, c2;
DROP TABLE p1, p2;
######################################################################
# Test for TRUNCATE
######################################################################
######################################################################
#
# Scenario #1: DML working on FK parent table BF aborted by DDL
# over child table
#
######################################################################
connection node_1;
SET SESSION wsrep_sync_wait=0;
CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
INSERT INTO p2 VALUES (1, 'INITIAL VALUE');
INSERT INTO p2 VALUES (2, 'INITIAL VALUE');
CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
INSERT INTO c1 VALUES (1,1);
CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk));
INSERT INTO c2 VALUES (1,1,1), (2,1,2);
connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
connection node_2;
SET SESSION wsrep_sync_wait=0;
TRUNCATE TABLE c1 ;
connection node_1;
COMMIT;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
connection node_2;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
######################################################################
#
# Scenario #2: DML working on FK parent table tries to replicate, but
# fails in certification for earlier DDL on child table
#
######################################################################
connection node_1;
BEGIN;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
TRUNCATE TABLE c1 ;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
COMMIT;
connection node_1a;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT 'I deadlocked';
I deadlocked
I deadlocked
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
connection node_2;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
######################################################################
#
# Scenario #3: 2 DMLs working on two FK parent tables try to replicate,
# but fails in certification for earlier DDL on child table
# which is child to both FK parents
#
######################################################################
connection node_1;
BEGIN;
connection node_1b;
BEGIN;
connection node_1a;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
TRUNCATE TABLE c2 ;
connection node_1a;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
connection node_1;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
COMMIT;
connection node_1b;
UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2;
COMMIT;
connection node_1a;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT 'I deadlocked';
I deadlocked
I deadlocked
connection node_1b;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT 'I deadlocked';
I deadlocked
I deadlocked
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
connection node_2;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
EXPECT_2
2
DROP TABLE c1, c2;
DROP TABLE p1, p2;

View File

@@ -45,34 +45,34 @@ connection node_2;
set session wsrep_sync_wait=15; set session wsrep_sync_wait=15;
insert into t1(value) values (3); insert into t1(value) values (3);
insert into t1(value) values (4); insert into t1(value) values (4);
select * from t2; select tbl, action from t2;
id tbl action tbl action
1 t1 INSERT t1 INSERT
3 t1 INSERT t1 INSERT
4 t1 INSERT t1 INSERT
6 t1 INSERT t1 INSERT
connection node_1; connection node_1;
drop trigger if exists log_insert; drop trigger if exists log_insert;
insert into t1(value) values (5); insert into t1(value) values (5);
select * from t2; select tbl, action from t2;
id tbl action tbl action
1 t1 INSERT t1 INSERT
3 t1 INSERT t1 INSERT
4 t1 INSERT t1 INSERT
6 t1 INSERT t1 INSERT
connection node_2; connection node_2;
insert into t1(value) values (6); insert into t1(value) values (6);
select * from t2; select tbl, action from t2;
id tbl action tbl action
1 t1 INSERT t1 INSERT
3 t1 INSERT t1 INSERT
4 t1 INSERT t1 INSERT
6 t1 INSERT t1 INSERT
connection node_1; connection node_1;
select * from t2; select tbl, action from t2;
id tbl action tbl action
1 t1 INSERT t1 INSERT
3 t1 INSERT t1 INSERT
4 t1 INSERT t1 INSERT
6 t1 INSERT t1 INSERT
drop table t1, t2; drop table t1, t2;

View File

@@ -0,0 +1,20 @@
#
# MDEV-24063
#
# my_bool wsrep_thd_is_aborting(const THD*):
# Assertion `((&(&thd->LOCK_thd_data)->m_mutex)->count > 0 &&
# pthread_equal(pthread_self(), (&(&thd->LOCK_thd_data)->m_mutex)->thread))' failed.
#
--source include/galera_cluster.inc
--connect node_2a, 127.0.0.1, root, , test, $NODE_MYPORT_2
--connection node_2a
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY);
--connection node_2
SET GLOBAL wsrep_on=OFF;
--source include/shutdown_mysqld.inc
--source include/start_mysqld.inc
DROP TABLE t1;

View File

@@ -0,0 +1,192 @@
#
# Test for MDL BF-BF lock conflict
# There are some DDL statements, which take extensive MDL lock for
# a table referenced by foreign key constraint from the actual affetec table.
# This extensive MDL lock may cause MDL BF-BF confclict situations, if the
# FK parent table is not listed as certification key in the replication write set.
# i.e. if replication allows such DDL to apply in parallel with regular DML operating
# on the FK parent table.
#
# This test has two scenarios, where DML modifies FK parent table in node 1,
# and offending DDL for FK child table is sent from node 2.
#
# param: $table_admin_command
# DDL table command to test, script will build full SQL statement:
# $table_admin_command TABLE c;
#
# param: $table_admin_command_end
# Optional additional SQL syntax to end the SQL statement, if any
# $table_admin_command TABLE c $table_admin_command_end;
#
# scenario 1, can be used to test if a DDL statement causes such MDL locking vulnerability.
# call this test script with some table DDL command in $table_admin_command
# if scenario 1 passes (especially COMMIT does fail for ER_LOCK_DEADLOCK),
# then this particular DDL is vulnerable. scenraio 2 should fail for this DDL
# unless code has not been fixed to append parent table certification keys for it.
#
--echo ######################################################################
--echo # Test for $table_admin_command $table_admin_command_end
--echo ######################################################################
--echo ######################################################################
--echo #
--echo # Scenario #1: DML working on FK parent table BF aborted by DDL
--echo # over child table
--echo #
--echo ######################################################################
--connection node_1
SET SESSION wsrep_sync_wait=0;
CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
CREATE TABLE p2 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
INSERT INTO p2 VALUES (1, 'INITIAL VALUE');
INSERT INTO p2 VALUES (2, 'INITIAL VALUE');
CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
INSERT INTO c1 VALUES (1,1);
CREATE TABLE c2 (pk INTEGER PRIMARY KEY, fk1 INTEGER, fk2 INTEGER, FOREIGN KEY (fk1) REFERENCES p1(pk), FOREIGN KEY (fk2) REFERENCES p2(pk));
INSERT INTO c2 VALUES (1,1,1), (2,1,2);
--connection node_1
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
--connection node_2
SET SESSION wsrep_sync_wait=0;
# wait for tables to be created in node 2 and all rows inserted as well
--let $wait_condition = SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/c%'
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 2 FROM c2
--source include/wait_condition.inc
# replicate the DDL to be tested
--eval $table_admin_command TABLE c1 $table_admin_command_end
--connection node_1
--error ER_LOCK_DEADLOCK
COMMIT;
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
--connection node_2
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
--echo ######################################################################
--echo #
--echo # Scenario #2: DML working on FK parent table tries to replicate, but
--echo # fails in certification for earlier DDL on child table
--echo #
--echo ######################################################################
--connection node_1
BEGIN;
# Block the applier on node #1 and issue DDL on node 2
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_set_sync_point.inc
--connection node_2
--eval $table_admin_command TABLE c1 $table_admin_command_end
--connection node_1a
--source include/galera_wait_sync_point.inc
--source include/galera_clear_sync_point.inc
--let $expected_cert_failures = `SELECT VARIABLE_VALUE+1 FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'`
--connection node_1
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
--send COMMIT
--connection node_1a
--let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'
--source include/wait_condition.inc
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_signal_sync_point.inc
--connection node_1
--error ER_LOCK_DEADLOCK
--reap
SELECT 'I deadlocked';
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
--connection node_2
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
--echo ######################################################################
--echo #
--echo # Scenario #3: 2 DMLs working on two FK parent tables try to replicate,
--echo # but fails in certification for earlier DDL on child table
--echo # which is child to both FK parents
--echo #
--echo ######################################################################
--connection node_1
BEGIN;
--connection node_1b
BEGIN;
--connection node_1a
# Block the applier on node #1 and issue DDL on node 2
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_set_sync_point.inc
--connection node_2
--eval $table_admin_command TABLE c2 $table_admin_command_end
--connection node_1a
--source include/galera_wait_sync_point.inc
--source include/galera_clear_sync_point.inc
--let $expected_cert_failures = `SELECT VARIABLE_VALUE+2 FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'`
--connection node_1
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
--send COMMIT
--connection node_1b
UPDATE p2 SET f2 = 'TO DEADLOCK' WHERE pk = 2;
--send COMMIT
--connection node_1a
--let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'
--source include/wait_condition.inc
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_signal_sync_point.inc
--connection node_1
--error ER_LOCK_DEADLOCK
--reap
SELECT 'I deadlocked';
--connection node_1b
--error ER_LOCK_DEADLOCK
--reap
SELECT 'I deadlocked';
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
--connection node_2
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
SELECT COUNT(*) AS EXPECT_2 FROM p2 WHERE f2 = 'INITIAL VALUE';
DROP TABLE c1, c2;
DROP TABLE p1, p2;

View File

@@ -0,0 +1,37 @@
#
# MDL BF-BF lock conflict
#
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
--source include/galera_have_debug_sync.inc
# sync point controlling session
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
--connection node_1a
SET SESSION wsrep_sync_wait=0;
# secondary conflicting DML victim session
--connect node_1b, 127.0.0.1, root, , test, $NODE_MYPORT_1
--connection node_1b
SET SESSION wsrep_sync_wait=0;
--let $table_admin_command = OPTIMIZE
--source galera_ddl_fk_conflict.inc
--source galera_ddl_fk_conflict_with_tmp.inc
--let $table_admin_command = REPAIR
--source galera_ddl_fk_conflict.inc
--source galera_ddl_fk_conflict_with_tmp.inc
--let $table_admin_command = ALTER
--let $table_admin_command_end = ENGINE=INNODB
--source galera_ddl_fk_conflict.inc
--let $table_admin_command = TRUNCATE
--let $table_admin_command_end =
--source galera_ddl_fk_conflict.inc
# CHECK and ANALYZE are not affected

View File

@@ -0,0 +1,69 @@
--echo ######################################################################
--echo # Test for $table_admin_command $table_admin_command_end
--echo ######################################################################
--connection node_1
SET SESSION wsrep_sync_wait=0;
CREATE TABLE p1 (pk INTEGER PRIMARY KEY, f2 CHAR(30));
INSERT INTO p1 VALUES (1, 'INITIAL VALUE');
CREATE TABLE c1 (pk INTEGER PRIMARY KEY, fk INTEGER, FOREIGN KEY (fk) REFERENCES p1(pk));
INSERT INTO c1 VALUES (1,1);
--echo ######################################################################
--echo #
--echo # Scenario #4: DML working on FK parent table tries to replicate, but
--echo # fails in certification for earlier DDL on child table
--echo # and another temporary table. TMP table should be skipped
--echo # but FK child table should be replicated with proper keys
--echo #
--echo ######################################################################
--connection node_1
BEGIN;
# Block the applier on node #1 and issue DDL on node 2
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_set_sync_point.inc
--connection node_2
# wait for tables to be created in node 2 and all rows inserted as well
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'test/c1'
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 1 FROM c1
--source include/wait_condition.inc
CREATE TEMPORARY TABLE tmp (i int);
--eval $table_admin_command TABLE c1, tmp $table_admin_command_end
DROP TABLE tmp;
--connection node_1a
--source include/galera_wait_sync_point.inc
--source include/galera_clear_sync_point.inc
--let $expected_cert_failures = `SELECT VARIABLE_VALUE+1 FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'`
--connection node_1
UPDATE p1 SET f2 = 'TO DEADLOCK' WHERE pk = 1;
--send COMMIT
--connection node_1a
--let $wait_condition = SELECT VARIABLE_VALUE = $expected_cert_failures FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_local_cert_failures'
--source include/wait_condition.inc
--let $galera_sync_point = apply_monitor_slave_enter_sync
--source include/galera_signal_sync_point.inc
--connection node_1
--error ER_LOCK_DEADLOCK
--reap
SELECT 'I deadlocked';
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
--connection node_2
SELECT COUNT(*) AS EXPECT_1 FROM p1 WHERE f2 = 'INITIAL VALUE';
DROP TABLE c1;
DROP TABLE p1;

View File

@@ -55,18 +55,18 @@ insert into t1(value) values (2);
set session wsrep_sync_wait=15; set session wsrep_sync_wait=15;
insert into t1(value) values (3); insert into t1(value) values (3);
insert into t1(value) values (4); insert into t1(value) values (4);
select * from t2; select tbl, action from t2;
--connection node_1 --connection node_1
drop trigger if exists log_insert; drop trigger if exists log_insert;
insert into t1(value) values (5); insert into t1(value) values (5);
select * from t2; select tbl, action from t2;
--connection node_2 --connection node_2
insert into t1(value) values (6); insert into t1(value) values (6);
select * from t2; select tbl, action from t2;
--connection node_1 --connection node_1
select * from t2; select tbl, action from t2;
drop table t1, t2; drop table t1, t2;

View File

@@ -1 +0,0 @@
--log-bin

View File

@@ -0,0 +1,9 @@
!include ../galera_2nodes.cnf
[mysqld.1]
log-bin
wsrep-debug=1
[mysqld.1]
log-bin
wsrep-debug=1

View File

@@ -1,5 +1,6 @@
--source include/galera_cluster.inc --source include/galera_cluster.inc
--source include/have_innodb.inc --source include/have_innodb.inc
--source include/force_restart.inc
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB; CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB; CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;

View File

@@ -22,3 +22,19 @@ i
1 1
UNLOCK TABLES; UNLOCK TABLES;
DROP TABLE t1; DROP TABLE t1;
#
# MDEV-23824 SIGSEGV in end_io_cache on REPAIR LOCAL TABLE for Aria table
#
CREATE TABLE t1 (i INT) ENGINE=Aria;
INSERT INTO t1 VALUES (1);
SET max_session_mem_used=50000;
REPAIR LOCAL TABLE t1 USE_FRM;
Table Op Msg_type Msg_text
t1 repair error Failed to open partially repaired table
Warnings:
Error 1290 The MariaDB server is running with the --max-thread-mem-used=50000 option so it cannot execute this statement
REPAIR LOCAL TABLE t1;
Table Op Msg_type Msg_text
test.t1 repair Error The MariaDB server is running with the --max-thread-mem-used=50000 option so it cannot execute this statement
test.t1 repair error Corrupt
DROP TABLE t1;

View File

@@ -22,3 +22,14 @@ SELECT * FROM INFORMATION_SCHEMA.TABLES;
SELECT * FROM t1; SELECT * FROM t1;
UNLOCK TABLES; UNLOCK TABLES;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-23824 SIGSEGV in end_io_cache on REPAIR LOCAL TABLE for Aria table
--echo #
CREATE TABLE t1 (i INT) ENGINE=Aria;
INSERT INTO t1 VALUES (1);
SET max_session_mem_used=50000;
REPAIR LOCAL TABLE t1 USE_FRM;
REPAIR LOCAL TABLE t1;
DROP TABLE t1;

View File

@@ -16,7 +16,6 @@ wait/synch/sxlock/innodb/dict_operation_lock
wait/synch/sxlock/innodb/fil_space_latch wait/synch/sxlock/innodb/fil_space_latch
wait/synch/sxlock/innodb/fts_cache_init_rw_lock wait/synch/sxlock/innodb/fts_cache_init_rw_lock
wait/synch/sxlock/innodb/fts_cache_rw_lock wait/synch/sxlock/innodb/fts_cache_rw_lock
wait/synch/sxlock/innodb/index_online_log
wait/synch/sxlock/innodb/index_tree_rw_lock wait/synch/sxlock/innodb/index_tree_rw_lock
wait/synch/sxlock/innodb/trx_i_s_cache_lock wait/synch/sxlock/innodb/trx_i_s_cache_lock
wait/synch/sxlock/innodb/trx_purge_latch wait/synch/sxlock/innodb/trx_purge_latch

View File

@@ -45,6 +45,10 @@ ERROR 42000: Incorrect column specifier for column 's'
create or replace table t (id int primary key, s date, e date, create or replace table t (id int primary key, s date, e date,
period for mytime(s,x)); period for mytime(s,x));
ERROR 42S22: Unknown column 'x' in 'mytime' ERROR 42S22: Unknown column 'x' in 'mytime'
# MDEV-18842: Unfortunate error message when the same column is used
# for application period start and end
create or replace table t (s date, t date, period for apt(s,s));
ERROR 42000: Column 's' specified twice
create or replace table t (id int primary key, s date, e date, create or replace table t (id int primary key, s date, e date,
period for mytime(s,e), period for mytime(s,e),
period for mytime2(s,e)); period for mytime2(s,e));

View File

@@ -31,6 +31,12 @@ create or replace table t (id int primary key, s time, e time,
--error ER_BAD_FIELD_ERROR --error ER_BAD_FIELD_ERROR
create or replace table t (id int primary key, s date, e date, create or replace table t (id int primary key, s date, e date,
period for mytime(s,x)); period for mytime(s,x));
--echo # MDEV-18842: Unfortunate error message when the same column is used
--echo # for application period start and end
--error ER_FIELD_SPECIFIED_TWICE
create or replace table t (s date, t date, period for apt(s,s));
--error ER_MORE_THAN_ONE_PERIOD --error ER_MORE_THAN_ONE_PERIOD
create or replace table t (id int primary key, s date, e date, create or replace table t (id int primary key, s date, e date,
period for mytime(s,e), period for mytime(s,e),

View File

@@ -22,7 +22,7 @@ START SLAVE IO_THREAD;
include/wait_for_slave_io_error.inc [errno=1236] include/wait_for_slave_io_error.inc [errno=1236]
connection master; connection master;
FLUSH BINARY LOGS; FLUSH BINARY LOGS;
PURGE BINARY LOGS TO 'master-bin.000002';; include/wait_for_purge.inc "master-bin.000002"
FLUSH BINARY LOGS DELETE_DOMAIN_ID=(11); FLUSH BINARY LOGS DELETE_DOMAIN_ID=(11);
SELECT @@global.gtid_binlog_pos, @@global.gtid_binlog_state; SELECT @@global.gtid_binlog_pos, @@global.gtid_binlog_state;
@@global.gtid_binlog_pos @@global.gtid_binlog_state @@global.gtid_binlog_pos @@global.gtid_binlog_state

View File

@@ -53,17 +53,11 @@ START SLAVE IO_THREAD;
# adjust the master binlog state # adjust the master binlog state
FLUSH BINARY LOGS; FLUSH BINARY LOGS;
--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1) --let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
--eval PURGE BINARY LOGS TO '$purge_to_binlog'; --let $purge_binlogs_to=$purge_to_binlog
--source include/wait_for_purge.inc
# with final removal of the extra domain # with final removal of the extra domain
###adding to debug info to catch the failure (1076):
--error 0,1076
--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID=($extra_domain_id) --eval FLUSH BINARY LOGS DELETE_DOMAIN_ID=($extra_domain_id)
if ($mysql_errno == 1076) {
--echo ### Failure "Could not delete gtid domain"
--source include/show_rpl_debug_info.inc
}
SELECT @@global.gtid_binlog_pos, @@global.gtid_binlog_state; SELECT @@global.gtid_binlog_pos, @@global.gtid_binlog_state;
--connection slave --connection slave

View File

@@ -449,7 +449,8 @@ mysqld_ld_preload_text() {
set_malloc_lib() { set_malloc_lib() {
malloc_lib="$1" malloc_lib="$1"
if expr "$malloc_lib" : "\(tcmalloc\|jemalloc\)" > /dev/null ; then if expr "$malloc_lib" : "\(tcmalloc\|jemalloc\)" > /dev/null ; then
if ! my_which ldconfig > /dev/null 2>&1 export PATH=$PATH:/sbin
if ! command -v ldconfig > /dev/null 2>&1
then then
log_error "ldconfig command not found, required for ldconfig -p" log_error "ldconfig command not found, required for ldconfig -p"
exit 1 exit 1

View File

@@ -728,7 +728,7 @@ public:
{ {
bytes_written = 0; bytes_written = 0;
} }
void harvest_bytes_written(ulonglong* counter) void harvest_bytes_written(Atomic_counter<uint64> *counter)
{ {
#ifndef DBUG_OFF #ifndef DBUG_OFF
char buf1[22],buf2[22]; char buf1[22],buf2[22];

View File

@@ -461,7 +461,7 @@ static inline int add_relay_log(Relay_log_info* rli,LOG_INFO* linfo)
DBUG_RETURN(1); DBUG_RETURN(1);
} }
rli->log_space_total += s.st_size; rli->log_space_total += s.st_size;
DBUG_PRINT("info",("log_space_total: %llu", rli->log_space_total)); DBUG_PRINT("info",("log_space_total: %llu", uint64(rli->log_space_total)));
DBUG_RETURN(0); DBUG_RETURN(0);
} }
@@ -1254,7 +1254,7 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset,
mysql_mutex_unlock(rli->relay_log.get_log_lock()); mysql_mutex_unlock(rli->relay_log.get_log_lock());
} }
err: err:
DBUG_PRINT("info",("log_space_total: %llu",rli->log_space_total)); DBUG_PRINT("info",("log_space_total: %llu", uint64(rli->log_space_total)));
mysql_mutex_unlock(&rli->data_lock); mysql_mutex_unlock(&rli->data_lock);
DBUG_RETURN(error); DBUG_RETURN(error);
} }

View File

@@ -240,7 +240,8 @@ public:
threads, the SQL thread sets it to unblock the I/O thread and make it threads, the SQL thread sets it to unblock the I/O thread and make it
temporarily forget about the constraint. temporarily forget about the constraint.
*/ */
ulonglong log_space_limit,log_space_total; ulonglong log_space_limit;
Atomic_counter<uint64> log_space_total;
bool ignore_log_space_limit; bool ignore_log_space_limit;
/* /*

View File

@@ -2819,7 +2819,7 @@ static bool wait_for_relay_log_space(Relay_log_info* rli)
DBUG_PRINT("info", ("log_space_limit=%llu log_space_total=%llu " DBUG_PRINT("info", ("log_space_limit=%llu log_space_total=%llu "
"ignore_log_space_limit=%d " "ignore_log_space_limit=%d "
"sql_force_rotate_relay=%d", "sql_force_rotate_relay=%d",
rli->log_space_limit, rli->log_space_total, rli->log_space_limit, uint64(rli->log_space_total),
(int) rli->ignore_log_space_limit, (int) rli->ignore_log_space_limit,
(int) rli->sql_force_rotate_relay)); (int) rli->sql_force_rotate_relay));
} }
@@ -5085,7 +5085,7 @@ Stopping slave I/O thread due to out-of-memory error from master");
{ {
DBUG_PRINT("info", ("log_space_limit=%llu log_space_total=%llu " DBUG_PRINT("info", ("log_space_limit=%llu log_space_total=%llu "
"ignore_log_space_limit=%d", "ignore_log_space_limit=%d",
rli->log_space_limit, rli->log_space_total, rli->log_space_limit, uint64(rli->log_space_total),
(int) rli->ignore_log_space_limit)); (int) rli->ignore_log_space_limit));
} }
#endif #endif

View File

@@ -9087,6 +9087,9 @@ bool mysql_show_create_user(THD *thd, LEX_USER *lex_user)
append_identifier(thd, &result, username, strlen(username)); append_identifier(thd, &result, username, strlen(username));
add_user_parameters(thd, &result, acl_user, false); add_user_parameters(thd, &result, acl_user, false);
if (acl_user->account_locked)
result.append(STRING_WITH_LEN(" ACCOUNT LOCK"));
if (acl_user->password_expired) if (acl_user->password_expired)
result.append(STRING_WITH_LEN(" PASSWORD EXPIRE")); result.append(STRING_WITH_LEN(" PASSWORD EXPIRE"));
else if (!acl_user->password_lifetime) else if (!acl_user->password_lifetime)
@@ -9098,9 +9101,6 @@ bool mysql_show_create_user(THD *thd, LEX_USER *lex_user)
result.append(STRING_WITH_LEN(" DAY")); result.append(STRING_WITH_LEN(" DAY"));
} }
if (acl_user->account_locked)
result.append(STRING_WITH_LEN(" ACCOUNT LOCK"));
protocol->prepare_for_resend(); protocol->prepare_for_resend();
protocol->store(result.ptr(), result.length(), result.charset()); protocol->store(result.ptr(), result.length(), result.charset());
if (protocol->write()) if (protocol->write())

View File

@@ -1,5 +1,5 @@
/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. /* Copyright (c) 2010, 2015, Oracle and/or its affiliates.
Copyright (c) 2011, 2019, MariaDB Copyright (c) 2011, 2020, MariaDB
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -31,7 +31,7 @@
#include "strfunc.h" #include "strfunc.h"
#include "sql_admin.h" #include "sql_admin.h"
#include "sql_statistics.h" #include "sql_statistics.h"
#include "wsrep_mysqld.h"
/* Prepare, run and cleanup for mysql_recreate_table() */ /* Prepare, run and cleanup for mysql_recreate_table() */
static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list) static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list)
@@ -90,10 +90,10 @@ static int send_check_errmsg(THD *thd, TABLE_LIST* table,
static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
HA_CHECK_OPT *check_opt) HA_CHECK_OPT *check_opt)
{ {
int error= 0; int error= 0, create_error= 0;
TABLE tmp_table, *table; TABLE tmp_table, *table;
TABLE_LIST *pos_in_locked_tables= 0; TABLE_LIST *pos_in_locked_tables= 0;
TABLE_SHARE *share; TABLE_SHARE *share= 0;
bool has_mdl_lock= FALSE; bool has_mdl_lock= FALSE;
char from[FN_REFLEN],tmp[FN_REFLEN+32]; char from[FN_REFLEN],tmp[FN_REFLEN+32];
const char **ext; const char **ext;
@@ -206,6 +206,17 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
HA_EXTRA_NOT_USED, NULL); HA_EXTRA_NOT_USED, NULL);
table_list->table= 0; table_list->table= 0;
} }
else
{
/*
Table open failed, maybe because we run out of memory.
Close all open tables and relaese all MDL locks
*/
tdc_release_share(share);
share->tdc->flush(thd, true);
share= 0;
}
/* /*
After this point we have an exclusive metadata lock on our table After this point we have an exclusive metadata lock on our table
in both cases when table was successfully open in mysql_admin_table() in both cases when table was successfully open in mysql_admin_table()
@@ -219,11 +230,8 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
goto end; goto end;
} }
if (dd_recreate_table(thd, table_list->db.str, table_list->table_name.str)) if (dd_recreate_table(thd, table_list->db.str, table_list->table_name.str))
{ create_error= send_check_errmsg(thd, table_list, "repair",
error= send_check_errmsg(thd, table_list, "repair",
"Failed generating table from .frm file"); "Failed generating table from .frm file");
goto end;
}
/* /*
'FALSE' for 'using_transactions' means don't postpone 'FALSE' for 'using_transactions' means don't postpone
invalidation till the end of a transaction, but do it invalidation till the end of a transaction, but do it
@@ -236,6 +244,8 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
"Failed restoring .MYD file"); "Failed restoring .MYD file");
goto end; goto end;
} }
if (create_error)
goto end;
if (thd->locked_tables_list.locked_tables()) if (thd->locked_tables_list.locked_tables())
{ {
@@ -263,7 +273,8 @@ end:
if (table == &tmp_table) if (table == &tmp_table)
{ {
closefrm(table); closefrm(table);
tdc_release_share(table->s); if (share)
tdc_release_share(share);
} }
/* In case of a temporary table there will be no metadata lock. */ /* In case of a temporary table there will be no metadata lock. */
if (unlikely(error) && has_mdl_lock) if (unlikely(error) && has_mdl_lock)
@@ -418,6 +429,50 @@ dbug_err:
return open_error; return open_error;
} }
#ifdef WITH_WSREP
/*
OPTIMIZE, REPAIR and ALTER may take MDL locks not only for the affected table, but
also for the table referenced by foreign key constraint.
This wsrep_toi_replication() function handles TOI replication for OPTIMIZE and REPAIR
so that certification keys for potential FK parent tables are also appended in the
write set.
ALTER TABLE case is handled elsewhere.
*/
static bool wsrep_toi_replication(THD *thd, TABLE_LIST *tables)
{
if (!WSREP(thd) || !WSREP_CLIENT(thd)) return false;
LEX *lex= thd->lex;
/* only handle OPTIMIZE and REPAIR here */
switch (lex->sql_command)
{
case SQLCOM_OPTIMIZE:
case SQLCOM_REPAIR:
break;
default:
return false;
}
close_thread_tables(thd);
wsrep::key_array keys;
wsrep_append_fk_parent_table(thd, tables, &keys);
/* now TOI replication, with no locks held */
if (keys.empty())
{
WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, tables);
} else {
WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, tables, &keys) {
return true;
}
}
return false;
wsrep_error_label:
return true;
}
#endif /* WITH_WSREP */
/* /*
RETURN VALUES RETURN VALUES
@@ -486,6 +541,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
close_thread_tables(thd); close_thread_tables(thd);
for (table= tables; table; table= table->next_local) for (table= tables; table; table= table->next_local)
table->table= NULL; table->table= NULL;
#ifdef WITH_WSREP
if (wsrep_toi_replication(thd, tables))
{
WSREP_INFO("wsrep TOI replication of has failed, skipping OPTIMIZE");
goto err;
}
#endif /* WITH_WSREP */
for (table= tables; table; table= table->next_local) for (table= tables; table; table= table->next_local)
{ {
@@ -592,6 +654,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
#endif #endif
DBUG_PRINT("admin", ("table: %p", table->table)); DBUG_PRINT("admin", ("table: %p", table->table));
if (table->schema_table)
{
result_code= HA_ADMIN_NOT_IMPLEMENTED;
goto send_result;
}
if (prepare_func) if (prepare_func)
{ {
DBUG_PRINT("admin", ("calling prepare_func")); DBUG_PRINT("admin", ("calling prepare_func"));
@@ -650,12 +718,6 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
goto send_result; goto send_result;
} }
if (table->schema_table)
{
result_code= HA_ADMIN_NOT_IMPLEMENTED;
goto send_result;
}
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify) if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
{ {
/* purecov: begin inspected */ /* purecov: begin inspected */
@@ -1338,10 +1400,10 @@ bool Sql_cmd_analyze_table::execute(THD *thd)
m_lex->first_select_lex()->table_list.first= first_table; m_lex->first_select_lex()->table_list.first= first_table;
m_lex->query_tables= first_table; m_lex->query_tables= first_table;
error:
#ifdef WITH_WSREP #ifdef WITH_WSREP
wsrep_error_label: wsrep_error_label:
#endif #endif /* WITH_WSREP */
error:
DBUG_RETURN(res); DBUG_RETURN(res);
} }
@@ -1380,7 +1442,6 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table, if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table,
FALSE, UINT_MAX, FALSE)) FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */ goto error; /* purecov: inspected */
WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table);
res= (specialflag & SPECIAL_NO_NEW_FUNC) ? res= (specialflag & SPECIAL_NO_NEW_FUNC) ?
mysql_recreate_table(thd, first_table, true) : mysql_recreate_table(thd, first_table, true) :
@@ -1399,9 +1460,6 @@ bool Sql_cmd_optimize_table::execute(THD *thd)
m_lex->query_tables= first_table; m_lex->query_tables= first_table;
error: error:
#ifdef WITH_WSREP
wsrep_error_label:
#endif
DBUG_RETURN(res); DBUG_RETURN(res);
} }
@@ -1416,7 +1474,6 @@ bool Sql_cmd_repair_table::execute(THD *thd)
if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table, if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table,
FALSE, UINT_MAX, FALSE)) FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */ goto error; /* purecov: inspected */
WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table);
res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "repair", res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "repair",
TL_WRITE, 1, TL_WRITE, 1,
MY_TEST(m_lex->check_opt.sql_flags & TT_USEFRM), MY_TEST(m_lex->check_opt.sql_flags & TT_USEFRM),
@@ -1435,8 +1492,5 @@ bool Sql_cmd_repair_table::execute(THD *thd)
m_lex->query_tables= first_table; m_lex->query_tables= first_table;
error: error:
#ifdef WITH_WSREP
wsrep_error_label:
#endif
DBUG_RETURN(res); DBUG_RETURN(res);
} }

View File

@@ -490,6 +490,25 @@ bool Sql_cmd_alter_table::execute(THD *thd)
if (check_grant(thd, priv_needed, first_table, FALSE, UINT_MAX, FALSE)) if (check_grant(thd, priv_needed, first_table, FALSE, UINT_MAX, FALSE))
DBUG_RETURN(TRUE); /* purecov: inspected */ DBUG_RETURN(TRUE); /* purecov: inspected */
#ifdef WITH_WSREP
if (WSREP(thd) && WSREP_CLIENT(thd) &&
(!thd->is_current_stmt_binlog_format_row() ||
!thd->find_temporary_table(first_table)))
{
wsrep::key_array keys;
wsrep_append_fk_parent_table(thd, first_table, &keys);
WSREP_TO_ISOLATION_BEGIN_ALTER(lex->name.str ? select_lex->db.str
: first_table->db.str,
lex->name.str ? lex->name.str
: first_table->table_name.str,
first_table, &alter_info, &keys,
used_engine ? &create_info : nullptr);
thd->variables.auto_increment_offset = 1;
thd->variables.auto_increment_increment = 1;
}
#endif
if (lex->name.str && !test_all_bits(priv, INSERT_ACL | CREATE_ACL)) if (lex->name.str && !test_all_bits(priv, INSERT_ACL | CREATE_ACL))
{ {
@@ -517,20 +536,6 @@ bool Sql_cmd_alter_table::execute(THD *thd)
thd->work_part_info= 0; thd->work_part_info= 0;
#endif #endif
#ifdef WITH_WSREP
if (WSREP(thd) &&
(!thd->is_current_stmt_binlog_format_row() ||
!thd->find_temporary_table(first_table)))
{
WSREP_TO_ISOLATION_BEGIN_ALTER((lex->name.str ? select_lex->db.str : first_table->db.str),
(lex->name.str ? lex->name.str : first_table->table_name.str),
first_table, &alter_info, used_engine ? &create_info : NULL);
thd->variables.auto_increment_offset = 1;
thd->variables.auto_increment_increment = 1;
}
#endif
result= mysql_alter_table(thd, &select_lex->db, &lex->name, result= mysql_alter_table(thd, &select_lex->db, &lex->name,
&create_info, &create_info,
first_table, first_table,

View File

@@ -3448,7 +3448,7 @@ public:
void awake_no_mutex(killed_state state_to_set); void awake_no_mutex(killed_state state_to_set);
void awake(killed_state state_to_set) void awake(killed_state state_to_set)
{ {
bool wsrep_on_local= WSREP_NNULL(this); bool wsrep_on_local= variables.wsrep_on;
/* /*
mutex locking order (LOCK_thd_data - LOCK_thd_kill)) requires mutex locking order (LOCK_thd_data - LOCK_thd_kill)) requires
to grab LOCK_thd_data here to grab LOCK_thd_data here

View File

@@ -4469,6 +4469,12 @@ public:
int add_period(Lex_ident name, Lex_ident_sys_st start, Lex_ident_sys_st end) int add_period(Lex_ident name, Lex_ident_sys_st start, Lex_ident_sys_st end)
{ {
if (lex_string_cmp(system_charset_info, &start, &end) == 0)
{
my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), start.str);
return 1;
}
Table_period_info &info= create_info.period_info; Table_period_info &info= create_info.period_info;
if (check_exists && info.name.streq(name)) if (check_exists && info.name.streq(name))

View File

@@ -427,9 +427,23 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
bool hton_can_recreate; bool hton_can_recreate;
#ifdef WITH_WSREP #ifdef WITH_WSREP
if (WSREP(thd) && if (WSREP(thd))
wsrep_to_isolation_begin(thd, table_ref->db.str, table_ref->table_name.str, NULL)) {
wsrep::key_array keys;
wsrep_append_fk_parent_table(thd, table_ref, &keys);
if (keys.empty())
{
WSREP_TO_ISOLATION_BEGIN_IF(table_ref->db.str, table_ref->table_name.str, NULL)
{
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
}
} else {
WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, table_ref, &keys)
{
DBUG_RETURN(TRUE);
}
}
}
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
if (lock_table(thd, table_ref, &hton_can_recreate)) if (lock_table(thd, table_ref, &hton_can_recreate))

View File

@@ -2501,7 +2501,7 @@ create:
Lex->pop_select(); //main select Lex->pop_select(); //main select
} }
| create_or_replace USER_SYM opt_if_not_exists clear_privileges | create_or_replace USER_SYM opt_if_not_exists clear_privileges
grant_list opt_require_clause opt_resource_options opt_account_locking opt_password_expiration grant_list opt_require_clause opt_resource_options opt_account_locking_and_opt_password_expiration
{ {
if (unlikely(Lex->set_command_with_check(SQLCOM_CREATE_USER, if (unlikely(Lex->set_command_with_check(SQLCOM_CREATE_USER,
$1 | $3))) $1 | $3)))
@@ -7312,7 +7312,7 @@ alter:
} OPTIONS_SYM '(' server_options_list ')' { } } OPTIONS_SYM '(' server_options_list ')' { }
/* ALTER USER foo is allowed for MySQL compatibility. */ /* ALTER USER foo is allowed for MySQL compatibility. */
| ALTER USER_SYM opt_if_exists clear_privileges grant_list | ALTER USER_SYM opt_if_exists clear_privileges grant_list
opt_require_clause opt_resource_options opt_account_locking opt_password_expiration opt_require_clause opt_resource_options opt_account_locking_and_opt_password_expiration
{ {
Lex->create_info.set($3); Lex->create_info.set($3);
Lex->sql_command= SQLCOM_ALTER_USER; Lex->sql_command= SQLCOM_ALTER_USER;
@@ -7348,39 +7348,46 @@ alter:
} stmt_end {} } stmt_end {}
; ;
opt_account_locking: account_locking_option:
/* Nothing */ {} LOCK_SYM
| ACCOUNT_SYM LOCK_SYM
{ {
Lex->account_options.account_locked= ACCOUNTLOCK_LOCKED; Lex->account_options.account_locked= ACCOUNTLOCK_LOCKED;
} }
| ACCOUNT_SYM UNLOCK_SYM | UNLOCK_SYM
{ {
Lex->account_options.account_locked= ACCOUNTLOCK_UNLOCKED; Lex->account_options.account_locked= ACCOUNTLOCK_UNLOCKED;
} }
; ;
opt_password_expiration:
/* Nothing */ {} opt_password_expire_option:
| PASSWORD_SYM EXPIRE_SYM /* empty */
{ {
Lex->account_options.password_expire= PASSWORD_EXPIRE_NOW; Lex->account_options.password_expire= PASSWORD_EXPIRE_NOW;
} }
| PASSWORD_SYM EXPIRE_SYM NEVER_SYM | NEVER_SYM
{ {
Lex->account_options.password_expire= PASSWORD_EXPIRE_NEVER; Lex->account_options.password_expire= PASSWORD_EXPIRE_NEVER;
} }
| PASSWORD_SYM EXPIRE_SYM DEFAULT | DEFAULT
{ {
Lex->account_options.password_expire= PASSWORD_EXPIRE_DEFAULT; Lex->account_options.password_expire= PASSWORD_EXPIRE_DEFAULT;
} }
| PASSWORD_SYM EXPIRE_SYM INTERVAL_SYM NUM DAY_SYM | INTERVAL_SYM NUM DAY_SYM
{ {
Lex->account_options.password_expire= PASSWORD_EXPIRE_INTERVAL; Lex->account_options.password_expire= PASSWORD_EXPIRE_INTERVAL;
if (!(Lex->account_options.num_expiration_days= atoi($4.str))) if (!(Lex->account_options.num_expiration_days= atoi($2.str)))
my_yyabort_error((ER_WRONG_VALUE, MYF(0), "DAY", $4.str)); my_yyabort_error((ER_WRONG_VALUE, MYF(0), "DAY", $2.str));
} }
; ;
opt_account_locking_and_opt_password_expiration:
/* empty */
| ACCOUNT_SYM account_locking_option
| PASSWORD_SYM EXPIRE_SYM opt_password_expire_option
| ACCOUNT_SYM account_locking_option PASSWORD_SYM EXPIRE_SYM opt_password_expire_option
| PASSWORD_SYM EXPIRE_SYM opt_password_expire_option ACCOUNT_SYM account_locking_option
;
ev_alter_on_schedule_completion: ev_alter_on_schedule_completion:
/* empty */ { $$= 0;} /* empty */ { $$= 0;}
| ON SCHEDULE_SYM ev_schedule_time { $$= 1; } | ON SCHEDULE_SYM ev_schedule_time { $$= 1; }

View File

@@ -245,6 +245,16 @@ void Wsrep_client_service::will_replay()
mysql_mutex_unlock(&LOCK_wsrep_replaying); mysql_mutex_unlock(&LOCK_wsrep_replaying);
} }
void Wsrep_client_service::signal_replayed()
{
DBUG_ASSERT(m_thd == current_thd);
mysql_mutex_lock(&LOCK_wsrep_replaying);
--wsrep_replaying;
DBUG_ASSERT(wsrep_replaying >= 0);
mysql_cond_broadcast(&COND_wsrep_replaying);
mysql_mutex_unlock(&LOCK_wsrep_replaying);
}
enum wsrep::provider::status Wsrep_client_service::replay() enum wsrep::provider::status Wsrep_client_service::replay()
{ {
@@ -273,14 +283,15 @@ enum wsrep::provider::status Wsrep_client_service::replay()
} }
delete replayer_thd; delete replayer_thd;
mysql_mutex_lock(&LOCK_wsrep_replaying);
--wsrep_replaying;
mysql_cond_broadcast(&COND_wsrep_replaying);
mysql_mutex_unlock(&LOCK_wsrep_replaying);
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
enum wsrep::provider::status Wsrep_client_service::replay_unordered()
{
DBUG_ASSERT(0);
return wsrep::provider::error_not_implemented;
}
void Wsrep_client_service::wait_for_replayers(wsrep::unique_lock<wsrep::mutex>& lock) void Wsrep_client_service::wait_for_replayers(wsrep::unique_lock<wsrep::mutex>& lock)
{ {
DBUG_ASSERT(m_thd == current_thd); DBUG_ASSERT(m_thd == current_thd);
@@ -300,6 +311,12 @@ void Wsrep_client_service::wait_for_replayers(wsrep::unique_lock<wsrep::mutex>&
lock.lock(); lock.lock();
} }
enum wsrep::provider::status Wsrep_client_service::commit_by_xid()
{
DBUG_ASSERT(0);
return wsrep::provider::error_not_implemented;
}
void Wsrep_client_service::debug_sync(const char* sync_point) void Wsrep_client_service::debug_sync(const char* sync_point)
{ {
DBUG_ASSERT(m_thd == current_thd); DBUG_ASSERT(m_thd == current_thd);

View File

@@ -48,8 +48,19 @@ public:
void emergency_shutdown() void emergency_shutdown()
{ throw wsrep::not_implemented_error(); } { throw wsrep::not_implemented_error(); }
void will_replay(); void will_replay();
void signal_replayed();
enum wsrep::provider::status replay(); enum wsrep::provider::status replay();
enum wsrep::provider::status replay_unordered();
void wait_for_replayers(wsrep::unique_lock<wsrep::mutex>&); void wait_for_replayers(wsrep::unique_lock<wsrep::mutex>&);
enum wsrep::provider::status commit_by_xid();
bool is_explicit_xa()
{
return false;
}
bool is_xa_rollback()
{
return false;
}
void debug_sync(const char*); void debug_sync(const char*);
void debug_crash(const char*); void debug_crash(const char*);
int bf_rollback(); int bf_rollback();

View File

@@ -1261,6 +1261,51 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr)
key_arr->keys_len= 0; key_arr->keys_len= 0;
} }
void
wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* tables, wsrep::key_array* keys)
{
if (!WSREP(thd) || !WSREP_CLIENT(thd)) return;
TABLE_LIST *table;
thd->mdl_context.release_transactional_locks();
uint counter;
MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
if (thd->open_temporary_tables(tables) ||
open_tables(thd, &tables, &counter, MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL))
{
WSREP_DEBUG("unable to open table for FK checks for %s", thd->query());
}
for (table= tables; table; table= table->next_local)
{
if (!is_temporary_table(table) && table->table)
{
FOREIGN_KEY_INFO *f_key_info;
List<FOREIGN_KEY_INFO> f_key_list;
table->table->file->get_foreign_key_list(thd, &f_key_list);
List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
while ((f_key_info=it++))
{
WSREP_DEBUG("appended fkey %s", f_key_info->referenced_table->str);
keys->push_back(wsrep_prepare_key_for_toi(f_key_info->referenced_db->str,
f_key_info->referenced_table->str,
wsrep::key::shared));
}
}
}
/* close the table and release MDL locks */
close_thread_tables(thd);
thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
for (table= tables; table; table= table->next_local)
{
table->table= NULL;
table->mdl_request.ticket= NULL;
}
}
/*! /*!
* @param db Database string * @param db Database string
* @param table Table string * @param table Table string
@@ -1511,10 +1556,11 @@ wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
return ret; return ret;
} }
wsrep::key_array wsrep_prepare_keys_for_toi(const char* db, wsrep::key_array wsrep_prepare_keys_for_toi(const char *db,
const char* table, const char *table,
const TABLE_LIST* table_list, const TABLE_LIST *table_list,
const Alter_info* alter_info) const Alter_info *alter_info,
const wsrep::key_array *fk_tables)
{ {
wsrep::key_array ret; wsrep::key_array ret;
if (db || table) if (db || table)
@@ -1534,8 +1580,13 @@ wsrep::key_array wsrep_prepare_keys_for_toi(const char* db,
ret.insert(ret.end(), fk.begin(), fk.end()); ret.insert(ret.end(), fk.begin(), fk.end());
} }
} }
if (fk_tables && !fk_tables->empty())
{
ret.insert(ret.end(), fk_tables->begin(), fk_tables->end());
}
return ret; return ret;
} }
/* /*
* Construct Query_log_Event from thd query and serialize it * Construct Query_log_Event from thd query and serialize it
* into buffer. * into buffer.
@@ -2069,9 +2120,10 @@ fail:
-1: TOI replication failed -1: TOI replication failed
*/ */
static int wsrep_TOI_begin(THD *thd, const char *db, const char *table, static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
const TABLE_LIST* table_list, const TABLE_LIST *table_list,
const Alter_info* alter_info, const Alter_info *alter_info,
const HA_CREATE_INFO* create_info) const wsrep::key_array *fk_tables,
const HA_CREATE_INFO *create_info)
{ {
DBUG_ASSERT(wsrep_OSU_method_get(thd) == WSREP_OSU_TOI); DBUG_ASSERT(wsrep_OSU_method_get(thd) == WSREP_OSU_TOI);
@@ -2102,7 +2154,7 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
struct wsrep_buf buff= { buf, buf_len }; struct wsrep_buf buff= { buf, buf_len };
wsrep::key_array key_array= wsrep::key_array key_array=
wsrep_prepare_keys_for_toi(db, table, table_list, alter_info); wsrep_prepare_keys_for_toi(db, table, table_list, alter_info, fk_tables);
if (thd->has_read_only_protection()) if (thd->has_read_only_protection())
{ {
@@ -2250,8 +2302,9 @@ static void wsrep_RSU_end(THD *thd)
int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list, const TABLE_LIST* table_list,
const Alter_info* alter_info, const Alter_info *alter_info,
const HA_CREATE_INFO* create_info) const wsrep::key_array *fk_tables,
const HA_CREATE_INFO *create_info)
{ {
/* /*
No isolation for applier or replaying threads. No isolation for applier or replaying threads.
@@ -2305,7 +2358,8 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
{ {
switch (wsrep_OSU_method_get(thd)) { switch (wsrep_OSU_method_get(thd)) {
case WSREP_OSU_TOI: case WSREP_OSU_TOI:
ret= wsrep_TOI_begin(thd, db_, table_, table_list, alter_info, create_info); ret= wsrep_TOI_begin(thd, db_, table_, table_list, alter_info, fk_tables,
create_info);
break; break;
case WSREP_OSU_RSU: case WSREP_OSU_RSU:
ret= wsrep_RSU_begin(thd, db_, table_); ret= wsrep_RSU_begin(thd, db_, table_);

View File

@@ -215,6 +215,7 @@ wsrep_sync_wait_upto (THD* thd, wsrep_gtid_t* upto, int timeout);
extern void wsrep_last_committed_id (wsrep_gtid_t* gtid); extern void wsrep_last_committed_id (wsrep_gtid_t* gtid);
extern int wsrep_check_opts(); extern int wsrep_check_opts();
extern void wsrep_prepend_PATH (const char* path); extern void wsrep_prepend_PATH (const char* path);
void wsrep_append_fk_parent_table(THD* thd, TABLE_LIST* table, wsrep::key_array* keys);
/* Other global variables */ /* Other global variables */
extern wsrep_seqno_t wsrep_locked_seqno; extern wsrep_seqno_t wsrep_locked_seqno;
@@ -362,8 +363,9 @@ struct HA_CREATE_INFO;
int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_, int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list, const TABLE_LIST* table_list,
const Alter_info* alter_info= NULL, const Alter_info* alter_info= nullptr,
const HA_CREATE_INFO* create_info= NULL); const wsrep::key_array *fk_tables= nullptr,
const HA_CREATE_INFO* create_info= nullptr);
bool wsrep_should_replicate_ddl(THD* thd, const enum legacy_db_type db_type); bool wsrep_should_replicate_ddl(THD* thd, const enum legacy_db_type db_type);
bool wsrep_should_replicate_ddl_iterate(THD* thd, const TABLE_LIST* table_list); bool wsrep_should_replicate_ddl_iterate(THD* thd, const TABLE_LIST* table_list);
@@ -607,6 +609,9 @@ void wsrep_deinit_server();
*/ */
enum wsrep::streaming_context::fragment_unit wsrep_fragment_unit(ulong unit); enum wsrep::streaming_context::fragment_unit wsrep_fragment_unit(ulong unit);
wsrep::key wsrep_prepare_key_for_toi(const char* db, const char* table,
enum wsrep::key::type type);
#else /* !WITH_WSREP */ #else /* !WITH_WSREP */
/* These macros are needed to compile MariaDB without WSREP support /* These macros are needed to compile MariaDB without WSREP support

View File

@@ -3483,7 +3483,7 @@ re_evict:
if (fix_block->page.ibuf_exist) { if (fix_block->page.ibuf_exist) {
fix_block->page.ibuf_exist = false; fix_block->page.ibuf_exist = false;
ibuf_merge_or_delete_for_page(fix_block, page_id, ibuf_merge_or_delete_for_page(fix_block, page_id,
zip_size, true); zip_size);
} }
if (rw_latch == RW_X_LATCH) { if (rw_latch == RW_X_LATCH) {
@@ -3550,7 +3550,7 @@ buf_page_get_gen(
{ {
rw_lock_x_lock_inline(&block->lock, 0, file, line); rw_lock_x_lock_inline(&block->lock, 0, file, line);
block->page.ibuf_exist= false; block->page.ibuf_exist= false;
ibuf_merge_or_delete_for_page(block, page_id, block->zip_size(), true); ibuf_merge_or_delete_for_page(block, page_id, block->zip_size());
if (rw_latch == RW_X_LATCH) if (rw_latch == RW_X_LATCH)
{ {
@@ -3823,7 +3823,7 @@ loop:
if (block->page.ibuf_exist) if (block->page.ibuf_exist)
{ {
if (!recv_recovery_is_on()) if (!recv_recovery_is_on())
ibuf_merge_or_delete_for_page(nullptr, page_id, zip_size, true); ibuf_merge_or_delete_for_page(nullptr, page_id, zip_size);
block->page.ibuf_exist= false; block->page.ibuf_exist= false;
} }
@@ -3885,7 +3885,7 @@ loop:
/* Delete possible entries for the page from the insert buffer: /* Delete possible entries for the page from the insert buffer:
such can exist if the page belonged to an index which was dropped */ such can exist if the page belonged to an index which was dropped */
if (!recv_recovery_is_on()) if (!recv_recovery_is_on())
ibuf_merge_or_delete_for_page(nullptr, page_id, zip_size, true); ibuf_merge_or_delete_for_page(nullptr, page_id, zip_size);
static_assert(FIL_PAGE_PREV + 4 == FIL_PAGE_NEXT, "adjacent"); static_assert(FIL_PAGE_PREV + 4 == FIL_PAGE_NEXT, "adjacent");
memset_aligned<8>(block->frame + FIL_PAGE_PREV, 0xff, 8); memset_aligned<8>(block->frame + FIL_PAGE_PREV, 0xff, 8);

View File

@@ -5268,87 +5268,3 @@ dict_tf_to_row_format_string(
ut_error; ut_error;
return(0); return(0);
} }
/** Look for any dictionary objects that are found in the given tablespace.
@param[in] space_id Tablespace ID to search for.
@return true if tablespace is empty. */
bool
dict_space_is_empty(
ulint space_id)
{
btr_pcur_t pcur;
const rec_t* rec;
mtr_t mtr;
bool found = false;
dict_sys_lock();
mtr_start(&mtr);
for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
rec != NULL;
rec = dict_getnext_system(&pcur, &mtr)) {
const byte* field;
ulint len;
ulint space_id_for_table;
field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_TABLES__SPACE, &len);
ut_ad(len == 4);
space_id_for_table = mach_read_from_4(field);
if (space_id_for_table == space_id) {
found = true;
}
}
mtr_commit(&mtr);
dict_sys_unlock();
return(!found);
}
/** Find the space_id for the given name in sys_tablespaces.
@param[in] name Tablespace name to search for.
@return the tablespace ID. */
ulint
dict_space_get_id(
const char* name)
{
btr_pcur_t pcur;
const rec_t* rec;
mtr_t mtr;
ulint name_len = strlen(name);
ulint id = ULINT_UNDEFINED;
dict_sys_lock();
mtr_start(&mtr);
for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLESPACES);
rec != NULL;
rec = dict_getnext_system(&pcur, &mtr)) {
const byte* field;
ulint len;
field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_TABLESPACES__NAME, &len);
ut_ad(len > 0);
ut_ad(len < OS_FILE_MAX_PATH);
if (len == name_len && !memcmp(name, field, len)) {
field = rec_get_nth_field_old(
rec, DICT_FLD__SYS_TABLESPACES__SPACE, &len);
ut_ad(len == 4);
id = mach_read_from_4(field);
/* This is normally called by dict_getnext_system()
at the end of the index. */
btr_pcur_close(&pcur);
break;
}
}
mtr_commit(&mtr);
dict_sys_unlock();
return(id);
}

View File

@@ -541,6 +541,7 @@ static PSI_mutex_info all_innodb_mutexes[] = {
PSI_KEY(ibuf_bitmap_mutex), PSI_KEY(ibuf_bitmap_mutex),
PSI_KEY(ibuf_mutex), PSI_KEY(ibuf_mutex),
PSI_KEY(ibuf_pessimistic_insert_mutex), PSI_KEY(ibuf_pessimistic_insert_mutex),
PSI_KEY(index_online_log),
PSI_KEY(log_sys_mutex), PSI_KEY(log_sys_mutex),
PSI_KEY(page_zip_stat_per_index_mutex), PSI_KEY(page_zip_stat_per_index_mutex),
PSI_KEY(purge_sys_pq_mutex), PSI_KEY(purge_sys_pq_mutex),
@@ -587,7 +588,6 @@ static PSI_rwlock_info all_innodb_rwlocks[] = {
PSI_RWLOCK_KEY(trx_i_s_cache_lock), PSI_RWLOCK_KEY(trx_i_s_cache_lock),
PSI_RWLOCK_KEY(trx_purge_latch), PSI_RWLOCK_KEY(trx_purge_latch),
PSI_RWLOCK_KEY(index_tree_rw_lock), PSI_RWLOCK_KEY(index_tree_rw_lock),
PSI_RWLOCK_KEY(index_online_log),
}; };
# endif /* UNIV_PFS_RWLOCK */ # endif /* UNIV_PFS_RWLOCK */
@@ -15264,24 +15264,6 @@ struct table_list_item {
const char* name; const char* name;
}; };
/** Structure to compare two st_tablename objects using their
db and tablename. It is used in the ordering of cascade_fk_set.
It returns true if the first argument precedes the second argument
and false otherwise. */
struct tablename_compare {
bool operator()(const st_handler_tablename lhs,
const st_handler_tablename rhs) const
{
int cmp = strcmp(lhs.db, rhs.db);
if (cmp == 0) {
cmp = strcmp(lhs.tablename, rhs.tablename);
}
return(cmp < 0);
}
};
/*****************************************************************//** /*****************************************************************//**
Checks if ALTER TABLE may change the storage engine of the table. Checks if ALTER TABLE may change the storage engine of the table.
Changing storage engines is not allowed for tables for which there Changing storage engines is not allowed for tables for which there

View File

@@ -51,12 +51,7 @@ struct ha_table_option_struct
uint encryption; /*!< DEFAULT, ON, OFF */ uint encryption; /*!< DEFAULT, ON, OFF */
ulonglong encryption_key_id; /*!< encryption key id */ ulonglong encryption_key_id; /*!< encryption key id */
}; };
/* JAN: TODO: MySQL 5.7 handler.h */
struct st_handler_tablename
{
const char *db;
const char *tablename;
};
/** The class defining a handle to an Innodb table */ /** The class defining a handle to an Innodb table */
class ha_innobase final : public handler class ha_innobase final : public handler
{ {

View File

@@ -4170,19 +4170,11 @@ insert buffer. If the page is not read, but created in the buffer pool, this
function deletes its buffered entries from the insert buffer; there can function deletes its buffered entries from the insert buffer; there can
exist entries for such a page if the page belonged to an index which exist entries for such a page if the page belonged to an index which
subsequently was dropped. subsequently was dropped.
@param[in,out] block if page has been read from disk, @param block X-latched page to try to apply changes to, or NULL to discard
pointer to the page x-latched, else NULL @param page_id page identifier
@param[in] page_id page id of the index page @param zip_size ROW_FORMAT=COMPRESSED page size, or 0 */
@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 void ibuf_merge_or_delete_for_page(buf_block_t *block, const page_id_t page_id,
@param[in] update_ibuf_bitmap normally this is set, but ulint zip_size)
if we have deleted or are deleting the tablespace, then we naturally do not
want to update a non-existent bitmap page */
void
ibuf_merge_or_delete_for_page(
buf_block_t* block,
const page_id_t page_id,
ulint zip_size,
bool update_ibuf_bitmap)
{ {
btr_pcur_t pcur; btr_pcur_t pcur;
#ifdef UNIV_IBUF_DEBUG #ifdef UNIV_IBUF_DEBUG
@@ -4211,16 +4203,10 @@ ibuf_merge_or_delete_for_page(
return; return;
} }
fil_space_t* space; fil_space_t* space = fil_space_t::get(page_id.space());
if (update_ibuf_bitmap) {
space = fil_space_t::get(page_id.space());
if (UNIV_UNLIKELY(!space)) { if (UNIV_UNLIKELY(!space)) {
/* Do not try to read the bitmap page from the
non-existent tablespace, delete the ibuf records */
block = NULL; block = NULL;
update_ibuf_bitmap = false;
} else { } else {
ulint bitmap_bits = 0; ulint bitmap_bits = 0;
@@ -4245,14 +4231,6 @@ ibuf_merge_or_delete_for_page(
return; return;
} }
} }
} else if (block != NULL
&& (ibuf_fixed_addr_page(page_id, physical_size)
|| fsp_descr_page(page_id, physical_size))) {
return;
} else {
space = NULL;
}
mem_heap_t* heap = mem_heap_create(512); mem_heap_t* heap = mem_heap_create(512);
@@ -4297,12 +4275,11 @@ loop:
ibuf.index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF, ibuf.index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
&pcur, &mtr); &pcur, &mtr);
if (block != NULL) { if (block) {
ut_ad(rw_lock_own(&block->lock, RW_LOCK_X)); ut_ad(rw_lock_own(&block->lock, RW_LOCK_X));
buf_block_buf_fix_inc(block, __FILE__, __LINE__); buf_block_buf_fix_inc(block, __FILE__, __LINE__);
rw_lock_x_lock(&block->lock); rw_lock_x_lock(&block->lock);
mtr.set_named_space(space);
mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX); mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX);
/* This is a user page (secondary index leaf page), /* This is a user page (secondary index leaf page),
but we pretend that it is a change buffer page in but we pretend that it is a change buffer page in
@@ -4311,7 +4288,9 @@ loop:
the block is io-fixed. Other threads must not try to the block is io-fixed. Other threads must not try to
latch an io-fixed block. */ latch an io-fixed block. */
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE); buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
} else if (update_ibuf_bitmap) { }
if (space) {
mtr.set_named_space(space); mtr.set_named_space(space);
} }
@@ -4467,7 +4446,7 @@ loop:
} }
reset_bit: reset_bit:
if (!update_ibuf_bitmap) { if (!space) {
} else if (buf_block_t* bitmap = ibuf_bitmap_get_map_page( } else if (buf_block_t* bitmap = ibuf_bitmap_get_map_page(
page_id, zip_size, &mtr)) { page_id, zip_size, &mtr)) {
/* FIXME: update the bitmap byte only once! */ /* FIXME: update the bitmap byte only once! */

View File

@@ -910,19 +910,6 @@ inline ulint dict_tf_get_zip_size(ulint flags)
: 0; : 0;
} }
/** Determine the extent size (in pages) for the given table
@param[in] table the table whose extent size is being
calculated.
@return extent size in pages (256, 128 or 64) */
inline ulint dict_table_extent_size(const dict_table_t* table)
{
if (ulint zip_size = table->space->zip_size()) {
return (1U << 20) / zip_size;
}
return FSP_EXTENT_SIZE;
}
/********************************************************************//** /********************************************************************//**
Checks if a column is in the ordering columns of the clustered index of a Checks if a column is in the ordering columns of the clustered index of a
table. Column prefixes are treated like whole columns. table. Column prefixes are treated like whole columns.
@@ -1803,20 +1790,6 @@ dict_table_decode_n_col(
ulint* n_col, ulint* n_col,
ulint* n_v_col); ulint* n_v_col);
/** Look for any dictionary objects that are found in the given tablespace.
@param[in] space_id Tablespace ID to search for.
@return true if tablespace is empty. */
bool
dict_space_is_empty(
ulint space_id);
/** Find the space_id for the given name in sys_tablespaces.
@param[in] name Tablespace name to search for.
@return the tablespace ID. */
ulint
dict_space_get_id(
const char* name);
/** Free the virtual column template /** Free the virtual column template
@param[in,out] vc_templ virtual column template */ @param[in,out] vc_templ virtual column template */
UNIV_INLINE UNIV_INLINE

View File

@@ -329,19 +329,11 @@ insert buffer. If the page is not read, but created in the buffer pool, this
function deletes its buffered entries from the insert buffer; there can function deletes its buffered entries from the insert buffer; there can
exist entries for such a page if the page belonged to an index which exist entries for such a page if the page belonged to an index which
subsequently was dropped. subsequently was dropped.
@param[in,out] block if page has been read from disk, @param block X-latched page to try to apply changes to, or NULL to discard
pointer to the page x-latched, else NULL @param page_id page identifier
@param[in] page_id page id of the index page @param zip_size ROW_FORMAT=COMPRESSED page size, or 0 */
@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 void ibuf_merge_or_delete_for_page(buf_block_t *block, const page_id_t page_id,
@param[in] update_ibuf_bitmap normally this is set, but ulint zip_size);
if we have deleted or are deleting the tablespace, then we naturally do not
want to update a non-existent bitmap page */
void
ibuf_merge_or_delete_for_page(
buf_block_t* block,
const page_id_t page_id,
ulint zip_size,
bool update_ibuf_bitmap);
/** Delete all change buffer entries for a tablespace, /** Delete all change buffer entries for a tablespace,
in DISCARD TABLESPACE, IMPORT TABLESPACE, or crash recovery. in DISCARD TABLESPACE, IMPORT TABLESPACE, or crash recovery.

View File

@@ -985,20 +985,6 @@ public:
/*------------------------------*/ /*------------------------------*/
char* detailed_error; /*!< detailed error message for last char* detailed_error; /*!< detailed error message for last
error, or empty. */ error, or empty. */
/* Lock wait statistics */
ulint n_rec_lock_waits;
/*!< Number of record lock waits,
might not be exactly correct. */
ulint n_table_lock_waits;
/*!< Number of table lock waits,
might not be exactly correct. */
ulint total_rec_lock_wait_time;
/*!< Total rec lock wait time up
to this moment. */
ulint total_table_lock_wait_time;
/*!< Total table lock wait time
up to this moment. */
rw_trx_hash_element_t *rw_trx_hash_element; rw_trx_hash_element_t *rw_trx_hash_element;
LF_PINS *rw_trx_hash_pins; LF_PINS *rw_trx_hash_pins;
ulint magic_n; ulint magic_n;

View File

@@ -4259,72 +4259,152 @@ os_file_set_umask(ulint umask)
} }
#ifdef _WIN32 #ifdef _WIN32
static int win32_get_block_size(HANDLE volume_handle, const char *volume_name)
/* Checks whether physical drive is on SSD.*/
static bool is_drive_on_ssd(DWORD nr)
{ {
STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR disk_alignment; char physical_drive_path[32];
STORAGE_PROPERTY_QUERY storage_query; snprintf(physical_drive_path, sizeof(physical_drive_path),
DWORD tmp; "\\\\.\\PhysicalDrive%lu", nr);
memset(&storage_query, 0, sizeof(storage_query)); HANDLE h= CreateFile(physical_drive_path, 0,
storage_query.PropertyId = StorageAccessAlignmentProperty; FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
storage_query.QueryType = PropertyStandardQuery; nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
if (h == INVALID_HANDLE_VALUE)
if (os_win32_device_io_control(volume_handle,
IOCTL_STORAGE_QUERY_PROPERTY,
&storage_query,
sizeof storage_query,
&disk_alignment,
sizeof disk_alignment,
&tmp) && tmp == sizeof disk_alignment) {
return disk_alignment.BytesPerPhysicalSector;
}
switch (GetLastError()) {
case ERROR_INVALID_FUNCTION:
case ERROR_NOT_SUPPORTED:
break;
default:
os_file_handle_error_no_exit(
volume_name,
"DeviceIoControl(IOCTL_STORAGE_QUERY_PROPERTY / StorageAccessAlignmentProperty)",
FALSE);
}
return 512;
}
static bool win32_is_ssd(HANDLE volume_handle)
{
DWORD tmp;
DEVICE_SEEK_PENALTY_DESCRIPTOR seek_penalty;
STORAGE_PROPERTY_QUERY storage_query;
memset(&storage_query, 0, sizeof(storage_query));
storage_query.PropertyId = StorageDeviceSeekPenaltyProperty;
storage_query.QueryType = PropertyStandardQuery;
if (os_win32_device_io_control(volume_handle,
IOCTL_STORAGE_QUERY_PROPERTY,
&storage_query,
sizeof storage_query,
&seek_penalty,
sizeof seek_penalty,
&tmp) && tmp == sizeof(seek_penalty)){
return !seek_penalty.IncursSeekPenalty;
}
DEVICE_TRIM_DESCRIPTOR trim;
storage_query.PropertyId = StorageDeviceTrimProperty;
if (os_win32_device_io_control(volume_handle,
IOCTL_STORAGE_QUERY_PROPERTY,
&storage_query,
sizeof storage_query,
&trim,
sizeof trim,
&tmp) && tmp == sizeof trim) {
return trim.TrimEnabled;
}
return false; return false;
DEVICE_SEEK_PENALTY_DESCRIPTOR seek_penalty;
STORAGE_PROPERTY_QUERY storage_query{};
storage_query.PropertyId= StorageDeviceSeekPenaltyProperty;
storage_query.QueryType= PropertyStandardQuery;
bool on_ssd= false;
DWORD bytes_written;
if (DeviceIoControl(h, IOCTL_STORAGE_QUERY_PROPERTY, &storage_query,
sizeof storage_query, &seek_penalty, sizeof seek_penalty,
&bytes_written, nullptr))
{
on_ssd= seek_penalty.IncursSeekPenalty;
}
else
{
on_ssd= false;
}
CloseHandle(h);
return on_ssd;
} }
/*
Checks whether volume is on SSD, by checking all physical drives
in that volume.
*/
static bool is_volume_on_ssd(const char *volume_mount_point)
{
char volume_name[MAX_PATH];
if (!GetVolumeNameForVolumeMountPoint(volume_mount_point, volume_name,
array_elements(volume_name)))
{
/* This can fail, e.g if file is on network share */
return false;
}
/* Chomp last backslash, this is needed to open volume.*/
size_t length= strlen(volume_name);
if (length && volume_name[length - 1] == '\\')
volume_name[length - 1]= 0;
/* Open volume handle */
HANDLE volume_handle= CreateFile(
volume_name, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
if (volume_handle == INVALID_HANDLE_VALUE)
return false;
/*
Enumerate all volume extends, check whether all of them are on SSD
*/
/* Anticipate common case where there is only one extent.*/
VOLUME_DISK_EXTENTS single_extent;
/* But also have a place to manage allocated data.*/
std::unique_ptr<BYTE[]> lifetime;
DWORD bytes_written;
VOLUME_DISK_EXTENTS *extents= nullptr;
if (DeviceIoControl(volume_handle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
nullptr, 0, &single_extent, sizeof(single_extent),
&bytes_written, nullptr))
{
/* Worked on the first try. Use the preallocated buffer.*/
extents= &single_extent;
}
else
{
VOLUME_DISK_EXTENTS *last_query= &single_extent;
while (GetLastError() == ERROR_MORE_DATA)
{
DWORD extentCount= last_query->NumberOfDiskExtents;
DWORD allocatedSize=
FIELD_OFFSET(VOLUME_DISK_EXTENTS, Extents[extentCount]);
lifetime.reset(new BYTE[allocatedSize]);
last_query= (VOLUME_DISK_EXTENTS *) lifetime.get();
if (DeviceIoControl(volume_handle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
nullptr, 0, last_query, allocatedSize,
&bytes_written, nullptr))
{
extents= last_query;
break;
}
}
}
CloseHandle(volume_handle);
if (!extents)
return false;
for (DWORD i= 0; i < extents->NumberOfDiskExtents; i++)
if (!is_drive_on_ssd(extents->Extents[i].DiskNumber))
return false;
return true;
}
#include <unordered_map>
static bool is_file_on_ssd(char *file_path)
{
/* Cache of volume_path => volume_info, protected by rwlock.*/
static std::unordered_map<std::string, bool> cache;
static SRWLOCK lock= SRWLOCK_INIT;
/* Preset result, in case something fails, e.g we're on network drive.*/
char volume_path[MAX_PATH];
if (!GetVolumePathName(file_path, volume_path, array_elements(volume_path)))
return false;
/* Try cached volume info first.*/
std::string volume_path_str(volume_path);
bool found;
bool result;
AcquireSRWLockShared(&lock);
auto e= cache.find(volume_path_str);
if ((found= e != cache.end()))
result= e->second;
ReleaseSRWLockShared(&lock);
if (found)
return result;
result= is_volume_on_ssd(volume_path);
/* Update cache */
AcquireSRWLockExclusive(&lock);
cache[volume_path_str]= result;
ReleaseSRWLockExclusive(&lock);
return result;
}
#endif #endif
/** Determine some file metadata when creating or reading the file. /** Determine some file metadata when creating or reading the file.
@@ -4361,48 +4441,12 @@ void fil_node_t::find_metadata(os_file_t file
space->atomic_write_supported = space->purpose == FIL_TYPE_TEMPORARY space->atomic_write_supported = space->purpose == FIL_TYPE_TEMPORARY
|| space->purpose == FIL_TYPE_IMPORT; || space->purpose == FIL_TYPE_IMPORT;
#ifdef _WIN32 #ifdef _WIN32
block_size = 512; on_ssd = is_file_on_ssd(name);
on_ssd = false; FILE_STORAGE_INFO info;
// Open volume for this file, find out it "physical bytes per sector" if (GetFileInformationByHandleEx(
char volume[MAX_PATH + 4]; file, FileStorageInfo, &info, sizeof(info))) {
if (!GetVolumePathName(name, volume + 4, MAX_PATH)) { block_size = info.PhysicalBytesPerSectorForAtomicity;
os_file_handle_error_no_exit(name,
"GetVolumePathName()", FALSE);
return;
}
// Special prefix required for volume names.
memcpy(volume, "\\\\.\\", 4);
size_t len = strlen(volume);
if (volume[len - 1] == '\\') {
// Trim trailing backslash from volume name.
volume[len - 1] = 0;
}
HANDLE volume_handle = CreateFile(volume, FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
0, OPEN_EXISTING, 0, 0);
if (volume_handle != INVALID_HANDLE_VALUE) {
block_size = win32_get_block_size(volume_handle, volume);
on_ssd = win32_is_ssd(volume_handle);
CloseHandle(volume_handle);
} else { } else {
/*
Report error, unless it is expected, e.g
missing permissions, or error when trying to
open volume for UNC share.
*/
if (GetLastError() != ERROR_ACCESS_DENIED
&& GetDriveType(volume) == DRIVE_FIXED) {
os_file_handle_error_no_exit(volume, "CreateFile()", FALSE);
}
}
/* Currently we support file block size up to 4KiB */
if (block_size > 4096) {
block_size = 4096;
} else if (block_size < 512) {
block_size = 512; block_size = 512;
} }
#else #else

View File

@@ -59,12 +59,12 @@ const dtuple_t trx_undo_metadata = {
static ulint trx_undo_left(const buf_block_t *undo_block, const byte *ptr) static ulint trx_undo_left(const buf_block_t *undo_block, const byte *ptr)
{ {
ut_ad(ptr >= &undo_block->frame[TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE]); ut_ad(ptr >= &undo_block->frame[TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE]);
ut_ad(ptr <= &undo_block->frame[srv_page_size - 10 - FIL_PAGE_DATA_END]);
/* The 10 is supposed to be an extra safety margin (and needed for /* The 10 is supposed to be an extra safety margin (and needed for
compatibility with older versions) */ compatibility with older versions) */
return srv_page_size - ulint(ptr - undo_block->frame) - lint left= srv_page_size - (ptr - undo_block->frame) -
(10 + FIL_PAGE_DATA_END); (10 + FIL_PAGE_DATA_END);
ut_ad(left >= 0);
return left < 0 ? 0 : static_cast<ulint>(left);
} }
/**********************************************************************//** /**********************************************************************//**

View File

@@ -460,10 +460,6 @@ void trx_t::free()
MEM_NOACCESS(&xid, sizeof xid); MEM_NOACCESS(&xid, sizeof xid);
MEM_NOACCESS(&mod_tables, sizeof mod_tables); MEM_NOACCESS(&mod_tables, sizeof mod_tables);
MEM_NOACCESS(&detailed_error, sizeof detailed_error); MEM_NOACCESS(&detailed_error, sizeof detailed_error);
MEM_NOACCESS(&n_rec_lock_waits, sizeof n_rec_lock_waits);
MEM_NOACCESS(&n_table_lock_waits, sizeof n_table_lock_waits);
MEM_NOACCESS(&total_rec_lock_wait_time, sizeof total_rec_lock_wait_time);
MEM_NOACCESS(&total_table_lock_wait_time, sizeof total_table_lock_wait_time);
MEM_NOACCESS(&magic_n, sizeof magic_n); MEM_NOACCESS(&magic_n, sizeof magic_n);
trx_pools->mem_free(this); trx_pools->mem_free(this);
} }

View File

@@ -2360,6 +2360,14 @@ static int initialize_variables_for_repair(HA_CHECK *param,
{ {
MARIA_SHARE *share= info->s; MARIA_SHARE *share= info->s;
/*
We have to clear these variables first, as the cleanup-in-case-of-error
handling may touch these.
*/
bzero((char*) sort_info, sizeof(*sort_info));
bzero((char*) sort_param, sizeof(*sort_param));
bzero(&info->rec_cache, sizeof(info->rec_cache));
if (share->data_file_type == NO_RECORD) if (share->data_file_type == NO_RECORD)
{ {
_ma_check_print_error(param, _ma_check_print_error(param,
@@ -2374,9 +2382,6 @@ static int initialize_variables_for_repair(HA_CHECK *param,
if (share->lock.update_status) if (share->lock.update_status)
(*share->lock.update_status)(info->lock.status_param); (*share->lock.update_status)(info->lock.status_param);
bzero((char*) sort_info, sizeof(*sort_info));
bzero((char*) sort_param, sizeof(*sort_param));
param->testflag|= T_REP; /* for easy checking */ param->testflag|= T_REP; /* for easy checking */
if (share->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) if (share->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
param->testflag|= T_CALC_CHECKSUM; param->testflag|= T_CALC_CHECKSUM;
@@ -2404,7 +2409,6 @@ static int initialize_variables_for_repair(HA_CHECK *param,
set_data_file_type(sort_info, info->s); set_data_file_type(sort_info, info->s);
sort_info->org_data_file_type= share->data_file_type; sort_info->org_data_file_type= share->data_file_type;
bzero(&info->rec_cache, sizeof(info->rec_cache));
info->rec_cache.file= info->dfile.file; info->rec_cache.file= info->dfile.file;
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
@@ -2891,9 +2895,13 @@ err:
_ma_reset_state(info); _ma_reset_state(info);
end_io_cache(&param->read_cache); end_io_cache(&param->read_cache);
if (sort_info.new_info)
{
end_io_cache(&sort_info.new_info->rec_cache); end_io_cache(&sort_info.new_info->rec_cache);
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
}
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
sort_param.sort_info->info->in_check_table= 0; sort_param.sort_info->info->in_check_table= 0;
/* this below could fail, shouldn't we detect error? */ /* this below could fail, shouldn't we detect error? */
if (got_error) if (got_error)
@@ -4110,10 +4118,13 @@ err:
maria_scan_end(sort_info.info); maria_scan_end(sort_info.info);
_ma_reset_state(info); _ma_reset_state(info);
if (sort_info.new_info)
{
end_io_cache(&sort_info.new_info->rec_cache); end_io_cache(&sort_info.new_info->rec_cache);
sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
}
end_io_cache(&param->read_cache); end_io_cache(&param->read_cache);
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
if (got_error) if (got_error)
{ {
if (! param->error_printed) if (! param->error_printed)
@@ -4642,10 +4653,13 @@ err:
the share by remove_io_thread() or it was not yet started (if the the share by remove_io_thread() or it was not yet started (if the
error happend before creating the thread). error happend before creating the thread).
*/ */
if (sort_info.new_info)
{
end_io_cache(&sort_info.new_info->rec_cache); end_io_cache(&sort_info.new_info->rec_cache);
sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
}
end_io_cache(&param->read_cache); end_io_cache(&param->read_cache);
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
sort_info.new_info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
/* /*
Destroy the new data cache in case of non-quick repair. All slave Destroy the new data cache in case of non-quick repair. All slave
threads did either detach from the share by remove_io_thread() threads did either detach from the share by remove_io_thread()

View File

@@ -30,6 +30,7 @@ int maria_delete_table(const char *name)
{ {
MARIA_HA *info; MARIA_HA *info;
myf sync_dir; myf sync_dir;
int got_error= 0, error;
DBUG_ENTER("maria_delete_table"); DBUG_ENTER("maria_delete_table");
#ifdef EXTRA_DEBUG #ifdef EXTRA_DEBUG
@@ -41,9 +42,13 @@ int maria_delete_table(const char *name)
Unfortunately it is necessary to open the table just to check this. We use Unfortunately it is necessary to open the table just to check this. We use
'open_for_repair' to be able to open even a crashed table. 'open_for_repair' to be able to open even a crashed table.
*/ */
my_errno= 0;
if (!(info= maria_open(name, O_RDONLY, HA_OPEN_FOR_REPAIR, 0))) if (!(info= maria_open(name, O_RDONLY, HA_OPEN_FOR_REPAIR, 0)))
{ {
sync_dir= 0; sync_dir= 0;
/* Ignore not found errors and wrong symlink errors */
if (my_errno != ENOENT && my_errno != HA_WRONG_CREATE_OPTION)
got_error= my_errno;;
} }
else else
{ {
@@ -78,7 +83,9 @@ int maria_delete_table(const char *name)
DBUG_RETURN(1); DBUG_RETURN(1);
} }
DBUG_RETURN(maria_delete_table_files(name, 0, sync_dir | MY_WME)); if (!(error= maria_delete_table_files(name, 0, sync_dir | MY_WME)))
error= got_error;
DBUG_RETURN(error);
} }
/** /**

View File

@@ -1476,7 +1476,7 @@ static void setup_key_functions(register MARIA_KEYDEF *keyinfo)
/** /**
@brief Function to save and store the header in the index file (.MYI) @brief Function to save and store the header in the index file (.MAI)
Operates under MARIA_SHARE::intern_lock if requested. Operates under MARIA_SHARE::intern_lock if requested.
Sets MARIA_SHARE::MARIA_STATE_INFO::is_of_horizon if transactional table. Sets MARIA_SHARE::MARIA_STATE_INFO::is_of_horizon if transactional table.