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 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_) \
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;
#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_, \
table_list_, NULL, create_info_)) \
table_list_, nullptr, nullptr, create_info_))\
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) && \
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;
#define WSREP_TO_ISOLATION_END \
@@ -55,6 +58,10 @@
if (WSREP(thd) && !thd->lex->no_write_to_binlog \
&& 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_) \
{ if (WSREP_CLIENT(thd_) && \
wsrep_sync_wait(thd_, before_)) goto wsrep_error_label; }
@@ -68,7 +75,8 @@
#define WSREP_DEBUG(...)
#define WSREP_ERROR(...)
#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_BEGIN_CREATE(db_, table_, table_list_, create_info_)
#define WSREP_TO_ISOLATION_BEGIN_WRTCHK(db_, table_, table_list_)

View File

@@ -130,5 +130,42 @@ connection default;
#
alter user user1@localhost account lock;
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 user2@localhost;

View File

@@ -137,6 +137,32 @@ alter user user1@localhost account lock;
--error ER_ACCOUNT_HAS_BEEN_LOCKED
--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 user2@localhost;

View File

@@ -647,6 +647,7 @@ sub run_test_server ($$$) {
# Client disconnected
mtr_verbose("Child closed socket");
$s->remove($sock);
$sock->close;
if (--$childs == 0){
return ("Completed", $test_failure, $completed, $extra_warnings);
}
@@ -816,6 +817,7 @@ sub run_test_server ($$$) {
# Test failure due to warnings, force is off
return ("Warnings in log", 1, $completed, $extra_warnings);
}
next;
}
elsif ($line =~ /^SPENT/) {
add_total_times($line);
@@ -4102,6 +4104,7 @@ sub run_testcase ($$) {
if (start_servers($tinfo))
{
report_failure_and_restart($tinfo);
unlink $path_current_testlog;
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;
insert into t1(value) values (3);
insert into t1(value) values (4);
select * from t2;
id tbl action
1 t1 INSERT
3 t1 INSERT
4 t1 INSERT
6 t1 INSERT
select tbl, action from t2;
tbl action
t1 INSERT
t1 INSERT
t1 INSERT
t1 INSERT
connection node_1;
drop trigger if exists log_insert;
insert into t1(value) values (5);
select * from t2;
id tbl action
1 t1 INSERT
3 t1 INSERT
4 t1 INSERT
6 t1 INSERT
select tbl, action from t2;
tbl action
t1 INSERT
t1 INSERT
t1 INSERT
t1 INSERT
connection node_2;
insert into t1(value) values (6);
select * from t2;
id tbl action
1 t1 INSERT
3 t1 INSERT
4 t1 INSERT
6 t1 INSERT
select tbl, action from t2;
tbl action
t1 INSERT
t1 INSERT
t1 INSERT
t1 INSERT
connection node_1;
select * from t2;
id tbl action
1 t1 INSERT
3 t1 INSERT
4 t1 INSERT
6 t1 INSERT
select tbl, action from t2;
tbl action
t1 INSERT
t1 INSERT
t1 INSERT
t1 INSERT
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;
insert into t1(value) values (3);
insert into t1(value) values (4);
select * from t2;
select tbl, action from t2;
--connection node_1
drop trigger if exists log_insert;
insert into t1(value) values (5);
select * from t2;
select tbl, action from t2;
--connection node_2
insert into t1(value) values (6);
select * from t2;
select tbl, action from t2;
--connection node_1
select * from t2;
select tbl, action from 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/have_innodb.inc
--source include/force_restart.inc
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;

View File

@@ -22,3 +22,19 @@ i
1
UNLOCK TABLES;
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;
UNLOCK TABLES;
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/fts_cache_init_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/trx_i_s_cache_lock
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,
period for mytime(s,x));
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,
period for mytime(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
create or replace table t (id int primary key, s date, e date,
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
create or replace table t (id int primary key, s date, e date,
period for mytime(s,e),

View File

@@ -22,7 +22,7 @@ START SLAVE IO_THREAD;
include/wait_for_slave_io_error.inc [errno=1236]
connection master;
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);
SELECT @@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
FLUSH BINARY LOGS;
--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
###adding to debug info to catch the failure (1076):
--error 0,1076
--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;
--connection slave

View File

@@ -449,7 +449,8 @@ mysqld_ld_preload_text() {
set_malloc_lib() {
malloc_lib="$1"
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
log_error "ldconfig command not found, required for ldconfig -p"
exit 1

View File

@@ -728,7 +728,7 @@ public:
{
bytes_written = 0;
}
void harvest_bytes_written(ulonglong* counter)
void harvest_bytes_written(Atomic_counter<uint64> *counter)
{
#ifndef DBUG_OFF
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);
}
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);
}
@@ -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());
}
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);
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
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;
/*

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 "
"ignore_log_space_limit=%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->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 "
"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));
}
#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));
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)
result.append(STRING_WITH_LEN(" PASSWORD EXPIRE"));
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"));
}
if (acl_user->account_locked)
result.append(STRING_WITH_LEN(" ACCOUNT LOCK"));
protocol->prepare_for_resend();
protocol->store(result.ptr(), result.length(), result.charset());
if (protocol->write())

View File

@@ -1,5 +1,5 @@
/* 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
it under the terms of the GNU General Public License as published by
@@ -31,7 +31,7 @@
#include "strfunc.h"
#include "sql_admin.h"
#include "sql_statistics.h"
#include "wsrep_mysqld.h"
/* Prepare, run and cleanup for mysql_recreate_table() */
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,
HA_CHECK_OPT *check_opt)
{
int error= 0;
int error= 0, create_error= 0;
TABLE tmp_table, *table;
TABLE_LIST *pos_in_locked_tables= 0;
TABLE_SHARE *share;
TABLE_SHARE *share= 0;
bool has_mdl_lock= FALSE;
char from[FN_REFLEN],tmp[FN_REFLEN+32];
const char **ext;
@@ -206,6 +206,17 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
HA_EXTRA_NOT_USED, NULL);
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
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;
}
if (dd_recreate_table(thd, table_list->db.str, table_list->table_name.str))
{
error= send_check_errmsg(thd, table_list, "repair",
create_error= send_check_errmsg(thd, table_list, "repair",
"Failed generating table from .frm file");
goto end;
}
/*
'FALSE' for 'using_transactions' means don't postpone
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");
goto end;
}
if (create_error)
goto end;
if (thd->locked_tables_list.locked_tables())
{
@@ -263,7 +273,8 @@ end:
if (table == &tmp_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. */
if (unlikely(error) && has_mdl_lock)
@@ -418,6 +429,50 @@ dbug_err:
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
@@ -486,6 +541,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
close_thread_tables(thd);
for (table= tables; table; table= table->next_local)
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)
{
@@ -592,6 +654,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
#endif
DBUG_PRINT("admin", ("table: %p", table->table));
if (table->schema_table)
{
result_code= HA_ADMIN_NOT_IMPLEMENTED;
goto send_result;
}
if (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;
}
if (table->schema_table)
{
result_code= HA_ADMIN_NOT_IMPLEMENTED;
goto send_result;
}
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
{
/* 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->query_tables= first_table;
error:
#ifdef WITH_WSREP
wsrep_error_label:
#endif
#endif /* WITH_WSREP */
error:
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,
FALSE, UINT_MAX, FALSE))
goto error; /* purecov: inspected */
WSREP_TO_ISOLATION_BEGIN_WRTCHK(NULL, NULL, first_table);
res= (specialflag & SPECIAL_NO_NEW_FUNC) ?
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;
error:
#ifdef WITH_WSREP
wsrep_error_label:
#endif
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,
FALSE, UINT_MAX, FALSE))
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",
TL_WRITE, 1,
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;
error:
#ifdef WITH_WSREP
wsrep_error_label:
#endif
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))
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))
{
@@ -517,20 +536,6 @@ bool Sql_cmd_alter_table::execute(THD *thd)
thd->work_part_info= 0;
#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,
&create_info,
first_table,

View File

@@ -3448,7 +3448,7 @@ public:
void awake_no_mutex(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
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)
{
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;
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;
#ifdef WITH_WSREP
if (WSREP(thd) &&
wsrep_to_isolation_begin(thd, table_ref->db.str, table_ref->table_name.str, NULL))
if (WSREP(thd))
{
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);
}
} else {
WSREP_TO_ISOLATION_BEGIN_FK_TABLES(NULL, NULL, table_ref, &keys)
{
DBUG_RETURN(TRUE);
}
}
}
#endif /* WITH_WSREP */
if (lock_table(thd, table_ref, &hton_can_recreate))

View File

@@ -2501,7 +2501,7 @@ create:
Lex->pop_select(); //main select
}
| 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,
$1 | $3)))
@@ -7312,7 +7312,7 @@ alter:
} OPTIONS_SYM '(' server_options_list ')' { }
/* ALTER USER foo is allowed for MySQL compatibility. */
| 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->sql_command= SQLCOM_ALTER_USER;
@@ -7348,39 +7348,46 @@ alter:
} stmt_end {}
;
opt_account_locking:
/* Nothing */ {}
| ACCOUNT_SYM LOCK_SYM
account_locking_option:
LOCK_SYM
{
Lex->account_options.account_locked= ACCOUNTLOCK_LOCKED;
}
| ACCOUNT_SYM UNLOCK_SYM
| UNLOCK_SYM
{
Lex->account_options.account_locked= ACCOUNTLOCK_UNLOCKED;
}
;
opt_password_expiration:
/* Nothing */ {}
| PASSWORD_SYM EXPIRE_SYM
opt_password_expire_option:
/* empty */
{
Lex->account_options.password_expire= PASSWORD_EXPIRE_NOW;
}
| PASSWORD_SYM EXPIRE_SYM NEVER_SYM
| NEVER_SYM
{
Lex->account_options.password_expire= PASSWORD_EXPIRE_NEVER;
}
| PASSWORD_SYM EXPIRE_SYM DEFAULT
| 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;
if (!(Lex->account_options.num_expiration_days= atoi($4.str)))
my_yyabort_error((ER_WRONG_VALUE, MYF(0), "DAY", $4.str));
if (!(Lex->account_options.num_expiration_days= atoi($2.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:
/* empty */ { $$= 0;}
| 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);
}
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()
{
@@ -273,14 +283,15 @@ enum wsrep::provider::status Wsrep_client_service::replay()
}
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);
}
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)
{
DBUG_ASSERT(m_thd == current_thd);
@@ -300,6 +311,12 @@ void Wsrep_client_service::wait_for_replayers(wsrep::unique_lock<wsrep::mutex>&
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)
{
DBUG_ASSERT(m_thd == current_thd);

View File

@@ -48,8 +48,19 @@ public:
void emergency_shutdown()
{ throw wsrep::not_implemented_error(); }
void will_replay();
void signal_replayed();
enum wsrep::provider::status replay();
enum wsrep::provider::status replay_unordered();
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_crash(const char*);
int bf_rollback();

View File

@@ -1261,6 +1261,51 @@ void wsrep_keys_free(wsrep_key_arr_t* key_arr)
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 table Table string
@@ -1514,7 +1559,8 @@ wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
wsrep::key_array wsrep_prepare_keys_for_toi(const char *db,
const char *table,
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;
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());
}
}
if (fk_tables && !fk_tables->empty())
{
ret.insert(ret.end(), fk_tables->begin(), fk_tables->end());
}
return ret;
}
/*
* Construct Query_log_Event from thd query and serialize it
* into buffer.
@@ -2071,6 +2122,7 @@ fail:
static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
const TABLE_LIST *table_list,
const Alter_info *alter_info,
const wsrep::key_array *fk_tables,
const HA_CREATE_INFO *create_info)
{
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 };
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())
{
@@ -2251,6 +2303,7 @@ static void wsrep_RSU_end(THD *thd)
int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
const TABLE_LIST* table_list,
const Alter_info *alter_info,
const wsrep::key_array *fk_tables,
const HA_CREATE_INFO *create_info)
{
/*
@@ -2305,7 +2358,8 @@ int wsrep_to_isolation_begin(THD *thd, const char *db_, const char *table_,
{
switch (wsrep_OSU_method_get(thd)) {
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;
case WSREP_OSU_RSU:
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 int wsrep_check_opts();
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 */
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_,
const TABLE_LIST* table_list,
const Alter_info* alter_info= NULL,
const HA_CREATE_INFO* create_info= NULL);
const Alter_info* alter_info= nullptr,
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_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);
wsrep::key wsrep_prepare_key_for_toi(const char* db, const char* table,
enum wsrep::key::type type);
#else /* !WITH_WSREP */
/* These macros are needed to compile MariaDB without WSREP support

View File

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

View File

@@ -5268,87 +5268,3 @@ dict_tf_to_row_format_string(
ut_error;
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_mutex),
PSI_KEY(ibuf_pessimistic_insert_mutex),
PSI_KEY(index_online_log),
PSI_KEY(log_sys_mutex),
PSI_KEY(page_zip_stat_per_index_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_purge_latch),
PSI_RWLOCK_KEY(index_tree_rw_lock),
PSI_RWLOCK_KEY(index_online_log),
};
# endif /* UNIV_PFS_RWLOCK */
@@ -15264,24 +15264,6 @@ struct table_list_item {
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.
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 */
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 */
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
exist entries for such a page if the page belonged to an index which
subsequently was dropped.
@param[in,out] block if page has been read from disk,
pointer to the page x-latched, else NULL
@param[in] page_id page id of the index page
@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] update_ibuf_bitmap normally this is set, but
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)
@param block X-latched page to try to apply changes to, or NULL to discard
@param page_id page identifier
@param 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,
ulint zip_size)
{
btr_pcur_t pcur;
#ifdef UNIV_IBUF_DEBUG
@@ -4211,16 +4203,10 @@ ibuf_merge_or_delete_for_page(
return;
}
fil_space_t* space;
if (update_ibuf_bitmap) {
space = fil_space_t::get(page_id.space());
fil_space_t* space = fil_space_t::get(page_id.space());
if (UNIV_UNLIKELY(!space)) {
/* Do not try to read the bitmap page from the
non-existent tablespace, delete the ibuf records */
block = NULL;
update_ibuf_bitmap = false;
} else {
ulint bitmap_bits = 0;
@@ -4245,14 +4231,6 @@ ibuf_merge_or_delete_for_page(
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);
@@ -4297,12 +4275,11 @@ loop:
ibuf.index, search_tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
&pcur, &mtr);
if (block != NULL) {
if (block) {
ut_ad(rw_lock_own(&block->lock, RW_LOCK_X));
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
rw_lock_x_lock(&block->lock);
mtr.set_named_space(space);
mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX);
/* This is a user page (secondary index leaf page),
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
latch an io-fixed block. */
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
} else if (update_ibuf_bitmap) {
}
if (space) {
mtr.set_named_space(space);
}
@@ -4467,7 +4446,7 @@ loop:
}
reset_bit:
if (!update_ibuf_bitmap) {
if (!space) {
} else if (buf_block_t* bitmap = ibuf_bitmap_get_map_page(
page_id, zip_size, &mtr)) {
/* FIXME: update the bitmap byte only once! */

View File

@@ -910,19 +910,6 @@ inline ulint dict_tf_get_zip_size(ulint flags)
: 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
table. Column prefixes are treated like whole columns.
@@ -1803,20 +1790,6 @@ dict_table_decode_n_col(
ulint* n_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
@param[in,out] vc_templ virtual column template */
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
exist entries for such a page if the page belonged to an index which
subsequently was dropped.
@param[in,out] block if page has been read from disk,
pointer to the page x-latched, else NULL
@param[in] page_id page id of the index page
@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] update_ibuf_bitmap normally this is set, but
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);
@param block X-latched page to try to apply changes to, or NULL to discard
@param page_id page identifier
@param 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,
ulint zip_size);
/** Delete all change buffer entries for a tablespace,
in DISCARD TABLESPACE, IMPORT TABLESPACE, or crash recovery.

View File

@@ -985,20 +985,6 @@ public:
/*------------------------------*/
char* detailed_error; /*!< detailed error message for last
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;
LF_PINS *rw_trx_hash_pins;
ulint magic_n;

View File

@@ -4259,72 +4259,152 @@ os_file_set_umask(ulint umask)
}
#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;
STORAGE_PROPERTY_QUERY storage_query;
DWORD tmp;
char physical_drive_path[32];
snprintf(physical_drive_path, sizeof(physical_drive_path),
"\\\\.\\PhysicalDrive%lu", nr);
memset(&storage_query, 0, sizeof(storage_query));
storage_query.PropertyId = StorageAccessAlignmentProperty;
storage_query.QueryType = PropertyStandardQuery;
HANDLE h= CreateFile(physical_drive_path, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
if (h == INVALID_HANDLE_VALUE)
return false;
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_PROPERTY_QUERY 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;
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;
}
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;
}
/*
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
/** 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->purpose == FIL_TYPE_IMPORT;
#ifdef _WIN32
block_size = 512;
on_ssd = false;
// Open volume for this file, find out it "physical bytes per sector"
char volume[MAX_PATH + 4];
if (!GetVolumePathName(name, volume + 4, MAX_PATH)) {
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);
on_ssd = is_file_on_ssd(name);
FILE_STORAGE_INFO info;
if (GetFileInformationByHandleEx(
file, FileStorageInfo, &info, sizeof(info))) {
block_size = info.PhysicalBytesPerSectorForAtomicity;
} 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;
}
#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)
{
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
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);
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(&mod_tables, sizeof mod_tables);
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);
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;
/*
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)
{
_ma_check_print_error(param,
@@ -2374,9 +2382,6 @@ static int initialize_variables_for_repair(HA_CHECK *param,
if (share->lock.update_status)
(*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 */
if (share->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
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);
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->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
@@ -2891,9 +2895,13 @@ err:
_ma_reset_state(info);
end_io_cache(&param->read_cache);
if (sort_info.new_info)
{
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);
}
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
sort_param.sort_info->info->in_check_table= 0;
/* this below could fail, shouldn't we detect error? */
if (got_error)
@@ -4110,10 +4118,13 @@ err:
maria_scan_end(sort_info.info);
_ma_reset_state(info);
if (sort_info.new_info)
{
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);
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 (! param->error_printed)
@@ -4642,10 +4653,13 @@ err:
the share by remove_io_thread() or it was not yet started (if the
error happend before creating the thread).
*/
if (sort_info.new_info)
{
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);
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
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;
myf sync_dir;
int got_error= 0, error;
DBUG_ENTER("maria_delete_table");
#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
'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)))
{
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
{
@@ -78,7 +83,9 @@ int maria_delete_table(const char *name)
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.
Sets MARIA_SHARE::MARIA_STATE_INFO::is_of_horizon if transactional table.