Merge branch '10.5' into 10.6

This commit is contained in:
Oleksandr Byelkin 2020-11-14 20:05:35 +01:00
commit 10aa576483
63 changed files with 2033 additions and 437 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_)) \
#define WSREP_TO_ISOLATION_BEGIN(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_) \
if (WSREP(thd) && wsrep_thd_is_local(thd) && \
wsrep_to_isolation_begin(thd, 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_, \
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

@ -3998,6 +3998,240 @@ YEAR d1 d2
DROP PROCEDURE p;
DROP TABLE t1,t2,t3,t4;
#
# MDEV-23619: recursive CTE used only in the second operand of UNION
#
create table t1 (
a bigint(10) not null auto_increment,
b int(5) not null,
c bigint(10) default null,
primary key (a)
) engine myisam;
insert into t1 values
(1,3,12), (2,7,15), (3,1,3), (4,3,1);
explain with recursive r_cte as
( select * from t1 as s
union
select t1.* from t1, r_cte as r where t1.c = r.a )
select 0 as b FROM dual union all select b FROM r_cte as t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
2 DERIVED s ALL NULL NULL NULL NULL 4
3 RECURSIVE UNION t1 ALL NULL NULL NULL NULL 4 Using where
3 RECURSIVE UNION <derived2> ref key0 key0 9 test.t1.c 2
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL
4 RECURSIVE UNION <derived2> ALL NULL NULL NULL NULL 4
with recursive r_cte as
( select * from t1 as s
union
select t1.* from t1, r_cte as r where t1.c = r.a )
select 0 as b FROM dual union all select b FROM r_cte as t;
b
0
3
7
1
3
analyze format=json with recursive r_cte as
( select * from t1 as s
union
select t1.* from t1, r_cte as r where t1.c = r.a )
select 0 as b FROM dual union all select b FROM r_cte as t;
ANALYZE
{
"query_block": {
"union_result": {
"table_name": "<union1,4>",
"access_type": "ALL",
"r_loops": 0,
"r_rows": null,
"query_specifications": [
{
"query_block": {
"select_id": 1,
"table": {
"message": "No tables used"
}
}
},
{
"query_block": {
"select_id": 4,
"operation": "UNION",
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"table": {
"table_name": "<derived2>",
"access_type": "ALL",
"r_loops": 1,
"rows": 4,
"r_rows": 4,
"r_table_time_ms": "REPLACED",
"r_other_time_ms": "REPLACED",
"filtered": 100,
"r_filtered": 100,
"materialized": {
"query_block": {
"recursive_union": {
"table_name": "<union2,3>",
"access_type": "ALL",
"r_loops": 0,
"r_rows": null,
"query_specifications": [
{
"query_block": {
"select_id": 2,
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"table": {
"table_name": "s",
"access_type": "ALL",
"r_loops": 1,
"rows": 4,
"r_rows": 4,
"r_table_time_ms": "REPLACED",
"r_other_time_ms": "REPLACED",
"filtered": 100,
"r_filtered": 100
}
}
},
{
"query_block": {
"select_id": 3,
"operation": "UNION",
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"table": {
"table_name": "t1",
"access_type": "ALL",
"r_loops": 1,
"rows": 4,
"r_rows": 4,
"r_table_time_ms": "REPLACED",
"r_other_time_ms": "REPLACED",
"filtered": 100,
"r_filtered": 100,
"attached_condition": "t1.c is not null"
},
"table": {
"table_name": "<derived2>",
"access_type": "ref",
"possible_keys": ["key0"],
"key": "key0",
"key_length": "9",
"used_key_parts": ["a"],
"ref": ["test.t1.c"],
"r_loops": 4,
"rows": 2,
"r_rows": 0.5,
"r_table_time_ms": "REPLACED",
"r_other_time_ms": "REPLACED",
"filtered": 100,
"r_filtered": 100
}
}
}
]
}
}
}
}
}
}
]
}
}
}
prepare stmt from "with recursive r_cte as
( select * from t1 as s
union
select t1.* from t1, r_cte as r where t1.c = r.a )
select 0 as b FROM dual union all select b FROM r_cte as t";
execute stmt;
b
0
3
7
1
3
execute stmt;
b
0
3
7
1
3
deallocate prepare stmt;
#checking hanging cte that uses a recursive cte
explain with h_cte as
( with recursive r_cte as
( select * from t1 as s
union
select t1.* from t1, r_cte as r where t1.c = r.a )
select 0 as b FROM dual union all select b FROM r_cte as t)
select * from t1 as tt;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY tt ALL NULL NULL NULL NULL 4
with h_cte as
( with recursive r_cte as
( select * from t1 as s
union
select t1.* from t1, r_cte as r where t1.c = r.a )
select 0 as b FROM dual union all select b FROM r_cte as t)
select * from t1 as tt;
a b c
1 3 12
2 7 15
3 1 3
4 3 1
analyze format=json with h_cte as
( with recursive r_cte as
( select * from t1 as s
union
select t1.* from t1, r_cte as r where t1.c = r.a )
select 0 as b FROM dual union all select b FROM r_cte as t)
select * from t1 as tt;
ANALYZE
{
"query_block": {
"select_id": 1,
"r_loops": 1,
"r_total_time_ms": "REPLACED",
"table": {
"table_name": "tt",
"access_type": "ALL",
"r_loops": 1,
"rows": 4,
"r_rows": 4,
"r_table_time_ms": "REPLACED",
"r_other_time_ms": "REPLACED",
"filtered": 100,
"r_filtered": 100
}
}
}
prepare stmt from "with h_cte as
( with recursive r_cte as
( select * from t1 as s
union
select t1.* from t1, r_cte as r where t1.c = r.a )
select 0 as b FROM dual union all select b FROM r_cte as t)
select * from t1 as tt";
execute stmt;
a b c
1 3 12
2 7 15
3 1 3
4 3 1
execute stmt;
a b c
1 3 12
2 7 15
3 1 3
4 3 1
deallocate prepare stmt;
drop table t1;
#
# End of 10.2 tests
#
#

View file

@ -2675,6 +2675,56 @@ SELECT * FROM t4;
DROP PROCEDURE p;
DROP TABLE t1,t2,t3,t4;
--echo #
--echo # MDEV-23619: recursive CTE used only in the second operand of UNION
--echo #
create table t1 (
a bigint(10) not null auto_increment,
b int(5) not null,
c bigint(10) default null,
primary key (a)
) engine myisam;
insert into t1 values
(1,3,12), (2,7,15), (3,1,3), (4,3,1);
let $q=
with recursive r_cte as
( select * from t1 as s
union
select t1.* from t1, r_cte as r where t1.c = r.a )
select 0 as b FROM dual union all select b FROM r_cte as t;
eval explain $q;
eval $q;
--source include/analyze-format.inc
eval analyze format=json $q;
eval prepare stmt from "$q";
execute stmt;
execute stmt;
deallocate prepare stmt;
--echo #checking hanging cte that uses a recursive cte
let $q1=
with h_cte as
( with recursive r_cte as
( select * from t1 as s
union
select t1.* from t1, r_cte as r where t1.c = r.a )
select 0 as b FROM dual union all select b FROM r_cte as t)
select * from t1 as tt;
eval explain $q1;
eval $q1;
--source include/analyze-format.inc
eval analyze format=json $q1;
eval prepare stmt from "$q1";
execute stmt;
execute stmt;
deallocate prepare stmt;
drop table t1;
--echo #
--echo # End of 10.2 tests
--echo #

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":XXX,"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,33 @@ 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;
--replace_regex /"version_id":[0-9]*,/"version_id":XXX,/
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

@ -2818,7 +2818,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));
}
@ -5084,7 +5084,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",
"Failed generating table from .frm file");
goto end;
}
create_error= send_check_errmsg(thd, table_list, "repair",
"Failed generating table from .frm file");
/*
'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
wsrep_error_label:
#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

@ -3447,7 +3447,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

@ -5430,12 +5430,14 @@ void st_select_lex::set_explain_type(bool on_the_fly)
/*
pos_in_table_list=NULL for e.g. post-join aggregation JOIN_TABs.
*/
if (tab->table && tab->table->pos_in_table_list &&
tab->table->pos_in_table_list->with &&
tab->table->pos_in_table_list->with->is_recursive)
if (!tab->table);
else if (const TABLE_LIST *pos= tab->table->pos_in_table_list)
{
uses_cte= true;
break;
if (pos->with && pos->with->is_recursive)
{
uses_cte= true;
break;
}
}
}
if (uses_cte)

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

@ -13778,6 +13778,9 @@ void JOIN::join_free()
for (tmp_unit= select_lex->first_inner_unit();
tmp_unit;
tmp_unit= tmp_unit->next_unit())
{
if (tmp_unit->with_element && tmp_unit->with_element->is_recursive)
continue;
for (sl= tmp_unit->first_select(); sl; sl= sl->next_select())
{
Item_subselect *subselect= sl->master_unit()->item;
@ -13795,7 +13798,7 @@ void JOIN::join_free()
/* Can't unlock if at least one JOIN is still needed */
can_unlock= can_unlock && full_local;
}
}
/*
We are not using tables anymore
Unlock all tables. We may be in an INSERT .... SELECT statement.

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))
DBUG_RETURN(TRUE);
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

@ -2541,13 +2541,7 @@ bool st_select_lex_unit::cleanup()
{
DBUG_RETURN(FALSE);
}
/*
When processing a PS/SP or an EXPLAIN command cleanup of a unit can
be performed immediately when the unit is reached in the cleanup
traversal initiated by the cleanup of the main unit.
*/
if (!thd->stmt_arena->is_stmt_prepare() && !thd->lex->describe &&
with_element && with_element->is_recursive && union_result)
if (with_element && with_element->is_recursive && union_result)
{
select_union_recursive *result= with_element->rec_result;
if (++result->cleanup_count == with_element->rec_outer_references)
@ -2729,27 +2723,31 @@ bool st_select_lex::cleanup()
if (join)
{
List_iterator<TABLE_LIST> ti(leaf_tables);
TABLE_LIST *tbl;
while ((tbl= ti++))
{
if (tbl->is_recursive_with_table() &&
!tbl->is_with_table_recursive_reference())
{
/*
If query is killed before open_and_process_table() for tbl
is called then 'with' is already set, but 'derived' is not.
*/
st_select_lex_unit *unit= tbl->with->spec;
error|= (bool) error | (uint) unit->cleanup();
}
}
DBUG_ASSERT((st_select_lex*)join->select_lex == this);
error= join->destroy();
delete join;
join= 0;
}
for (TABLE_LIST *tbl= get_table_list(); tbl; tbl= tbl->next_local)
{
if (tbl->is_recursive_with_table() &&
!tbl->is_with_table_recursive_reference())
{
/*
If query is killed before open_and_process_table() for tbl
is called then 'with' is already set, but 'derived' is not.
*/
st_select_lex_unit *unit= tbl->with->spec;
error|= (bool) error | (uint) unit->cleanup();
}
}
for (SELECT_LEX_UNIT *lex_unit= first_inner_unit(); lex_unit ;
lex_unit= lex_unit->next_unit())
{
if (lex_unit->with_element && lex_unit->with_element->is_recursive)
continue;
error= (bool) ((uint) error | (uint) lex_unit->cleanup());
}
inner_refs_list.empty();
@ -2769,8 +2767,12 @@ void st_select_lex::cleanup_all_joins(bool full)
join->cleanup(full);
for (unit= first_inner_unit(); unit; unit= unit->next_unit())
{
if (unit->with_element && unit->with_element->is_recursive)
continue;
for (sl= unit->first_select(); sl; sl= sl->next_select())
sl->cleanup_all_joins(full);
}
DBUG_VOID_RETURN;
}

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
@ -1511,10 +1556,11 @@ wsrep_prepare_keys_for_alter_add_fk(const char* child_table_db,
return ret;
}
wsrep::key_array wsrep_prepare_keys_for_toi(const char* db,
const char* table,
const TABLE_LIST* table_list,
const Alter_info* alter_info)
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 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.
@ -2069,9 +2120,10 @@ fail:
-1: TOI replication failed
*/
static int wsrep_TOI_begin(THD *thd, const char *db, const char *table,
const TABLE_LIST* table_list,
const Alter_info* alter_info,
const HA_CREATE_INFO* create_info)
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())
{
@ -2250,8 +2302,9 @@ 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 HA_CREATE_INFO* create_info)
const Alter_info *alter_info,
const wsrep::key_array *fk_tables,
const HA_CREATE_INFO *create_info)
{
/*
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)) {
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)
{
@ -3772,18 +3772,29 @@ loop:
ut_ad(0);
break;
case BUF_BLOCK_FILE_PAGE:
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
if (!mtr->have_x_latch(*block))
{
const auto num_fix_count= mtr->get_fix_count(block) + 1;
while (block->page.io_fix() != BUF_IO_NONE ||
num_fix_count != block->page.buf_fix_count())
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
{
mysql_mutex_unlock(&buf_pool.mutex);
os_thread_yield();
mysql_mutex_lock(&buf_pool.mutex);
while (block->page.io_fix() != BUF_IO_NONE ||
block->page.buf_fix_count() != 1)
{
timespec abstime;
set_timespec_nsec(abstime, 1000000);
mysql_cond_timedwait(&buf_pool.done_flush_list, &buf_pool.mutex,
&abstime);
}
}
rw_lock_x_lock(&block->lock);
mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
}
else
{
ut_ad(!block->page.ibuf_exist);
#ifdef BTR_CUR_HASH_ADAPT
ut_ad(!block->index);
#endif
}
rw_lock_x_lock(&block->lock);
#ifdef BTR_CUR_HASH_ADAPT
drop_hash_entry= block->index;
#endif
@ -3808,6 +3819,7 @@ loop:
buf_page_free_descriptor(&block->page);
block= free_block;
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
break;
}
@ -3818,12 +3830,10 @@ loop:
btr_search_drop_page_hash_index(block);
#endif /* BTR_CUR_HASH_ADAPT */
mtr_memo_push(mtr, block, MTR_MEMO_PAGE_X_FIX);
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 +3895,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

@ -528,6 +528,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),
@ -574,7 +575,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 */
@ -15005,24 +15005,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,47 +4203,33 @@ ibuf_merge_or_delete_for_page(
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)) {
/* 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;
ibuf_mtr_start(&mtr);
buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(
page_id, zip_size, &mtr);
if (bitmap_page
&& fil_page_get_type(bitmap_page->frame)
!= FIL_PAGE_TYPE_ALLOCATED) {
bitmap_bits = ibuf_bitmap_page_get_bits(
bitmap_page->frame, page_id, zip_size,
IBUF_BITMAP_BUFFERED, &mtr);
}
ibuf_mtr_commit(&mtr);
if (!bitmap_bits) {
/* No changes are buffered for this page. */
space->release();
return;
}
}
} else if (block != NULL
&& (ibuf_fixed_addr_page(page_id, physical_size)
|| fsp_descr_page(page_id, physical_size))) {
return;
if (UNIV_UNLIKELY(!space)) {
block = NULL;
} else {
space = NULL;
ulint bitmap_bits = 0;
ibuf_mtr_start(&mtr);
buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(
page_id, zip_size, &mtr);
if (bitmap_page
&& fil_page_get_type(bitmap_page->frame)
!= FIL_PAGE_TYPE_ALLOCATED) {
bitmap_bits = ibuf_bitmap_page_get_bits(
bitmap_page->frame, page_id, zip_size,
IBUF_BITMAP_BUFFERED, &mtr);
}
ibuf_mtr_commit(&mtr);
if (!bitmap_bits) {
/* No changes are buffered for this page. */
space->release();
return;
}
}
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.

View file

@ -330,6 +330,24 @@ public:
return(true);
}
/**
Iterate over each block and call the functor.
@return false if iteration was terminated. */
template <typename Functor>
bool for_each_block(const Functor& functor) const
{
for (typename list_t::iterator it = m_list.begin(),
end = m_list.end();
it != end; ++it) {
if (!functor(&*it)) {
return false;
}
}
return(true);
}
/**
Iterate over all the blocks in reverse and call the iterator
@return false if iteration was terminated. */

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

@ -151,6 +151,10 @@ struct mtr_t {
return old_mode;
}
/** Check if we are holding a block latch in exclusive mode
@param block buffer pool block to search for */
bool have_x_latch(const buf_block_t &block) const;
/** Copy the tablespaces associated with the mini-transaction
(needed for generating FILE_MODIFY records)
@param[in] mtr mini-transaction that may modify

View file

@ -506,7 +506,7 @@ the pass value == 0. */
bool
rw_lock_own(
/*========*/
rw_lock_t* lock, /*!< in: rw-lock */
const rw_lock_t*lock, /*!< in: rw-lock */
ulint lock_type) /*!< in: lock type: RW_LOCK_S,
RW_LOCK_X */
MY_ATTRIBUTE((warn_unused_result));

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

@ -893,29 +893,48 @@ inline std::pair<lsn_t,bool> mtr_t::finish_write(ulint len)
return std::make_pair(start_lsn, flush);
}
/** Find buffer fix count of the given block acquired by the
mini-transaction */
struct FindBlock
/** Find out whether a block was X-latched by the mini-transaction */
struct FindBlockX
{
int32_t num_fix;
const buf_block_t *const block;
const buf_block_t &block;
FindBlock(const buf_block_t *block_buf): num_fix(0), block(block_buf) {}
FindBlockX(const buf_block_t &block): block(block) {}
bool operator()(const mtr_memo_slot_t* slot)
/** @return whether the block was not found x-latched */
bool operator()(const mtr_memo_slot_t *slot) const
{
if (slot->object == block)
num_fix++;
return true;
return slot->object != &block || slot->type == MTR_MEMO_PAGE_X_FIX;
}
};
uint32_t mtr_t::get_fix_count(const buf_block_t *block) const
#ifdef UNIV_DEBUG
/** Assert that the block is not present in the mini-transaction */
struct FindNoBlock
{
Iterate<FindBlock> iteration((FindBlock(block)));
if (m_memo.for_each_block(iteration))
return iteration.functor.num_fix;
return 0;
const buf_block_t &block;
FindNoBlock(const buf_block_t &block): block(block) {}
/** @return whether the block was not found */
bool operator()(const mtr_memo_slot_t *slot) const
{
return slot->object != &block;
}
};
#endif /* UNIV_DEBUG */
bool mtr_t::have_x_latch(const buf_block_t &block) const
{
if (m_memo.for_each_block(CIterate<FindBlockX>(FindBlockX(block))))
{
ut_ad(m_memo.for_each_block(CIterate<FindNoBlock>(FindNoBlock(block))));
ut_ad(!memo_contains_flagged(&block,
MTR_MEMO_PAGE_S_FIX | MTR_MEMO_PAGE_SX_FIX |
MTR_MEMO_BUF_FIX | MTR_MEMO_MODIFY));
return false;
}
ut_ad(rw_lock_own(&block.lock, RW_LOCK_X));
return true;
}
#ifdef UNIV_DEBUG
@ -931,13 +950,13 @@ bool mtr_t::memo_contains(const rw_lock_t &lock, mtr_memo_type_t type)
switch (type) {
case MTR_MEMO_X_LOCK:
ut_ad(rw_lock_own(const_cast<rw_lock_t*>(&lock), RW_LOCK_X));
ut_ad(rw_lock_own(&lock, RW_LOCK_X));
break;
case MTR_MEMO_SX_LOCK:
ut_ad(rw_lock_own(const_cast<rw_lock_t*>(&lock), RW_LOCK_SX));
ut_ad(rw_lock_own(&lock, RW_LOCK_SX));
break;
case MTR_MEMO_S_LOCK:
ut_ad(rw_lock_own(const_cast<rw_lock_t*>(&lock), RW_LOCK_S));
ut_ad(rw_lock_own(&lock, RW_LOCK_S));
break;
default:
break;

View file

@ -4262,72 +4262,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;
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;
}
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;
else
{
on_ssd= false;
}
return 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
/** Determine some file metadata when creating or reading the file.
@ -4364,48 +4444,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

@ -990,7 +990,7 @@ the pass value == 0.
bool
rw_lock_own(
/*========*/
rw_lock_t* lock, /*!< in: rw-lock */
const rw_lock_t*lock, /*!< in: rw-lock */
ulint lock_type) /*!< in: lock type: RW_LOCK_S,
RW_LOCK_X */
{

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);
end_io_cache(&sort_info.new_info->rec_cache);
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);
}
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
sort_info.new_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);
end_io_cache(&sort_info.new_info->rec_cache);
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).
*/
end_io_cache(&sort_info.new_info->rec_cache);
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.

View file

@ -96,7 +96,7 @@ void sql_print_error(const char *format, ...)
/*** end of encryption tweaks and stubs ****************************/
IO_CACHE info;
static IO_CACHE info;
#define CACHE_SIZE 16384
#define INFO_TAIL ", pos_in_file = %llu, pos_in_mem = %lu", \

@ -1 +1 @@
Subproject commit 2da6e4894e1df5d1db51db2bbc49255e02251b9d
Subproject commit 41a6e9dad79c921134e44cf974b6b7ca3b84e538