Merge remote-tracking branch 'origin/10.3' into 10.4
This commit is contained in:
commit
9c0f5a252b
@ -47,7 +47,7 @@ IF(CMAKE_C_COMPILER MATCHES "icl")
|
|||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
ADD_DEFINITIONS(-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE)
|
ADD_DEFINITIONS(-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE)
|
||||||
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0600)
|
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0A00)
|
||||||
# We do not want the windows.h macros min/max
|
# We do not want the windows.h macros min/max
|
||||||
ADD_DEFINITIONS(-DNOMINMAX)
|
ADD_DEFINITIONS(-DNOMINMAX)
|
||||||
# Speed up build process excluding unused header files
|
# Speed up build process excluding unused header files
|
||||||
|
@ -10,9 +10,9 @@ t1 CREATE TABLE `t1` (
|
|||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
insert into t1 values (100,100);
|
insert into t1 values (100,100);
|
||||||
insert into t1 values (1,1);
|
insert into t1 values (1,1);
|
||||||
ERROR 23000: CONSTRAINT `a` failed for `test`.`t1`
|
ERROR 23000: CONSTRAINT `t1.a` failed for `test`.`t1`
|
||||||
insert into t1 values (20,1);
|
insert into t1 values (20,1);
|
||||||
ERROR 23000: CONSTRAINT `b` failed for `test`.`t1`
|
ERROR 23000: CONSTRAINT `t1.b` failed for `test`.`t1`
|
||||||
insert into t1 values (20,30);
|
insert into t1 values (20,30);
|
||||||
ERROR 23000: CONSTRAINT `min` failed for `test`.`t1`
|
ERROR 23000: CONSTRAINT `min` failed for `test`.`t1`
|
||||||
insert into t1 values (500,500);
|
insert into t1 values (500,500);
|
||||||
@ -60,7 +60,7 @@ t1 CREATE TABLE `t1` (
|
|||||||
CONSTRAINT `CONSTRAINT_1` CHECK (`a` + `b` + `c` < 500)
|
CONSTRAINT `CONSTRAINT_1` CHECK (`a` + `b` + `c` < 500)
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
insert into t1 values(105,105,105);
|
insert into t1 values(105,105,105);
|
||||||
ERROR 23000: CONSTRAINT `c` failed for `test`.`t1`
|
ERROR 23000: CONSTRAINT `t1.c` failed for `test`.`t1`
|
||||||
insert into t1 values(249,249,9);
|
insert into t1 values(249,249,9);
|
||||||
ERROR 23000: CONSTRAINT `CONSTRAINT_1` failed for `test`.`t1`
|
ERROR 23000: CONSTRAINT `CONSTRAINT_1` failed for `test`.`t1`
|
||||||
insert into t1 values(105,105,9);
|
insert into t1 values(105,105,9);
|
||||||
@ -145,7 +145,7 @@ ERROR HY000: Function or expression '@b' cannot be used in the CHECK clause of `
|
|||||||
create table t1 (a int check (a = 1));
|
create table t1 (a int check (a = 1));
|
||||||
insert t1 values (1);
|
insert t1 values (1);
|
||||||
insert t1 values (2);
|
insert t1 values (2);
|
||||||
ERROR 23000: CONSTRAINT `a` failed for `test`.`t1`
|
ERROR 23000: CONSTRAINT `t1.a` failed for `test`.`t1`
|
||||||
insert t1 values (NULL);
|
insert t1 values (NULL);
|
||||||
select * from t1;
|
select * from t1;
|
||||||
a
|
a
|
||||||
@ -165,13 +165,13 @@ ERROR 22007: Truncated incorrect DOUBLE value: 'Ken'
|
|||||||
SHOW WARNINGS;
|
SHOW WARNINGS;
|
||||||
Level Code Message
|
Level Code Message
|
||||||
Error 1292 Truncated incorrect DOUBLE value: 'Ken'
|
Error 1292 Truncated incorrect DOUBLE value: 'Ken'
|
||||||
Error 4025 CONSTRAINT `FirstName` failed for `test`.`t1`
|
Error 4025 CONSTRAINT `t1.FirstName` failed for `test`.`t1`
|
||||||
INSERT INTO t1 VALUES (NULL, 'Ken'),(NULL, 'Brian');
|
INSERT INTO t1 VALUES (NULL, 'Ken'),(NULL, 'Brian');
|
||||||
ERROR 22007: Truncated incorrect DOUBLE value: 'Ken'
|
ERROR 22007: Truncated incorrect DOUBLE value: 'Ken'
|
||||||
SHOW WARNINGS;
|
SHOW WARNINGS;
|
||||||
Level Code Message
|
Level Code Message
|
||||||
Error 1292 Truncated incorrect DOUBLE value: 'Ken'
|
Error 1292 Truncated incorrect DOUBLE value: 'Ken'
|
||||||
Error 4025 CONSTRAINT `FirstName` failed for `test`.`t1`
|
Error 4025 CONSTRAINT `t1.FirstName` failed for `test`.`t1`
|
||||||
INSERT IGNORE INTO t1 VALUES (NULL, 'Ken');
|
INSERT IGNORE INTO t1 VALUES (NULL, 'Ken');
|
||||||
Warnings:
|
Warnings:
|
||||||
Warning 1292 Truncated incorrect DOUBLE value: 'Ken'
|
Warning 1292 Truncated incorrect DOUBLE value: 'Ken'
|
||||||
@ -197,3 +197,28 @@ EmployeeID FirstName
|
|||||||
5 Ken
|
5 Ken
|
||||||
6 Brian
|
6 Brian
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# MDEV-16630: Ambiguous error message when check constraint
|
||||||
|
# matches table name
|
||||||
|
#
|
||||||
|
use test;
|
||||||
|
drop table if exists t;
|
||||||
|
create table t(a int, b int check(b>0),
|
||||||
|
constraint b check(a<b), constraint a check(a>0),
|
||||||
|
constraint x check (a>10));
|
||||||
|
show create table t;
|
||||||
|
Table Create Table
|
||||||
|
t CREATE TABLE `t` (
|
||||||
|
`a` int(11) DEFAULT NULL,
|
||||||
|
`b` int(11) DEFAULT NULL CHECK (`b` > 0),
|
||||||
|
CONSTRAINT `b` CHECK (`a` < `b`),
|
||||||
|
CONSTRAINT `a` CHECK (`a` > 0),
|
||||||
|
CONSTRAINT `x` CHECK (`a` > 10)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
# Field constraint 'b' will fail
|
||||||
|
insert into t values (-1, 0);
|
||||||
|
ERROR 23000: CONSTRAINT `t.b` failed for `test`.`t`
|
||||||
|
# Table constraint 'b' will fail
|
||||||
|
insert into t values (1,1);
|
||||||
|
ERROR 23000: CONSTRAINT `b` failed for `test`.`t`
|
||||||
|
drop table t;
|
||||||
|
@ -135,3 +135,31 @@ INSERT INTO t1 VALUES (NULL, 'Ken'),(NULL, 'Brian');
|
|||||||
set sql_mode=default;
|
set sql_mode=default;
|
||||||
select * from t1;
|
select * from t1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-16630: Ambiguous error message when check constraint
|
||||||
|
--echo # matches table name
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
use test;
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
create table t(a int, b int check(b>0),
|
||||||
|
constraint b check(a<b), constraint a check(a>0),
|
||||||
|
constraint x check (a>10));
|
||||||
|
|
||||||
|
show create table t;
|
||||||
|
|
||||||
|
# Generate error when field constraint 'b' is violated
|
||||||
|
--echo # Field constraint 'b' will fail
|
||||||
|
--error ER_CONSTRAINT_FAILED
|
||||||
|
insert into t values (-1, 0);
|
||||||
|
|
||||||
|
# Generate error when table constraint 'b' is violated.
|
||||||
|
--echo # Table constraint 'b' will fail
|
||||||
|
--error ER_CONSTRAINT_FAILED
|
||||||
|
insert into t values (1,1);
|
||||||
|
|
||||||
|
drop table t;
|
||||||
|
@ -1472,3 +1472,17 @@ SELECT LEFT(a, 10), LENGTH(a) FROM t1;
|
|||||||
LEFT(a, 10) LENGTH(a)
|
LEFT(a, 10) LENGTH(a)
|
||||||
aaaaaaaaaa 255
|
aaaaaaaaaa 255
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# MDEV-16729 VARCHAR COMPRESSED is created with a wrong length for multi-byte character sets
|
||||||
|
#
|
||||||
|
CREATE OR REPLACE TABLE t1 (a VARCHAR(1000) CHARACTER SET utf8 COMPRESSED);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` varchar(1000) /*!100301 COMPRESSED*/ CHARACTER SET utf8 DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1';
|
||||||
|
COLUMN_TYPE
|
||||||
|
varchar(1000) /*!100301 COMPRESSED*/
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -170,3 +170,14 @@ CREATE TABLE t1(a TINYTEXT COMPRESSED);
|
|||||||
INSERT INTO t1 VALUES(REPEAT('a', 255));
|
INSERT INTO t1 VALUES(REPEAT('a', 255));
|
||||||
SELECT LEFT(a, 10), LENGTH(a) FROM t1;
|
SELECT LEFT(a, 10), LENGTH(a) FROM t1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-16729 VARCHAR COMPRESSED is created with a wrong length for multi-byte character sets
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE OR REPLACE TABLE t1 (a VARCHAR(1000) CHARACTER SET utf8 COMPRESSED);
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1';
|
||||||
|
DROP TABLE t1;
|
||||||
|
@ -7,7 +7,7 @@ t1 CREATE TABLE `t1` (
|
|||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
insert into t1 values (1);
|
insert into t1 values (1);
|
||||||
insert into t1 values (0);
|
insert into t1 values (0);
|
||||||
ERROR 23000: CONSTRAINT `a` failed for `test`.`t1`
|
ERROR 23000: CONSTRAINT `t1.a` failed for `test`.`t1`
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a int, b int, check (a>b));
|
create table t1 (a int, b int, check (a>b));
|
||||||
show create table t1;
|
show create table t1;
|
||||||
|
4
mysql-test/main/create_replace_tmp.result
Normal file
4
mysql-test/main/create_replace_tmp.result
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
CREATE TEMPORARY TABLE t (i INT);
|
||||||
|
CREATE or replace TABLE t AS SELECT * FROM t;
|
||||||
|
DROP TEMPORARY TABLE t;
|
||||||
|
DROP TABLE t;
|
4
mysql-test/main/create_replace_tmp.test
Normal file
4
mysql-test/main/create_replace_tmp.test
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
CREATE TEMPORARY TABLE t (i INT);
|
||||||
|
CREATE or replace TABLE t AS SELECT * FROM t;
|
||||||
|
DROP TEMPORARY TABLE t;
|
||||||
|
DROP TABLE t;
|
@ -3269,6 +3269,43 @@ select 3, 0*(@d:=@d+1) from qn where @d<1
|
|||||||
select * from qn;
|
select * from qn;
|
||||||
ERROR 42000: This version of MariaDB doesn't yet support 'mix of ALL and DISTINCT UNION operations in recursive CTE spec'
|
ERROR 42000: This version of MariaDB doesn't yet support 'mix of ALL and DISTINCT UNION operations in recursive CTE spec'
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# MDEV-16629: function with recursive CTE using a base table
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (id int);
|
||||||
|
INSERT INTO t1 VALUES (0), (1),(2);
|
||||||
|
WITH recursive cte AS
|
||||||
|
(SELECT id FROM t1 UNION SELECT 3 FROM cte)
|
||||||
|
SELECT count(id) FROM cte;
|
||||||
|
count(id)
|
||||||
|
4
|
||||||
|
CREATE OR REPLACE FUNCTION func() RETURNS int
|
||||||
|
RETURN
|
||||||
|
(
|
||||||
|
WITH recursive cte AS
|
||||||
|
(SELECT id FROM t1 UNION SELECT 3 FROM cte)
|
||||||
|
SELECT count(id) FROM cte
|
||||||
|
);
|
||||||
|
SELECT func();
|
||||||
|
func()
|
||||||
|
4
|
||||||
|
DROP FUNCTION func;
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# MDEV-16661: function with recursive CTE using no base tables
|
||||||
|
# (fixed by the patch for MDEV-16629)
|
||||||
|
#
|
||||||
|
CREATE OR REPLACE FUNCTION func() RETURNS int
|
||||||
|
RETURN
|
||||||
|
(
|
||||||
|
WITH RECURSIVE cte AS
|
||||||
|
(SELECT 1 as id UNION SELECT * FROM cte)
|
||||||
|
SELECT count(id) FROM cte
|
||||||
|
);
|
||||||
|
SELECT func();
|
||||||
|
func()
|
||||||
|
1
|
||||||
|
DROP FUNCTION func;
|
||||||
# Start of 10.3 tests
|
# Start of 10.3 tests
|
||||||
#
|
#
|
||||||
# MDEV-14217 [db crash] Recursive CTE when SELECT includes new field
|
# MDEV-14217 [db crash] Recursive CTE when SELECT includes new field
|
||||||
|
@ -2283,6 +2283,47 @@ select * from qn;
|
|||||||
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-16629: function with recursive CTE using a base table
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (id int);
|
||||||
|
INSERT INTO t1 VALUES (0), (1),(2);
|
||||||
|
|
||||||
|
WITH recursive cte AS
|
||||||
|
(SELECT id FROM t1 UNION SELECT 3 FROM cte)
|
||||||
|
SELECT count(id) FROM cte;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION func() RETURNS int
|
||||||
|
RETURN
|
||||||
|
(
|
||||||
|
WITH recursive cte AS
|
||||||
|
(SELECT id FROM t1 UNION SELECT 3 FROM cte)
|
||||||
|
SELECT count(id) FROM cte
|
||||||
|
);
|
||||||
|
|
||||||
|
SELECT func();
|
||||||
|
|
||||||
|
DROP FUNCTION func;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-16661: function with recursive CTE using no base tables
|
||||||
|
--echo # (fixed by the patch for MDEV-16629)
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION func() RETURNS int
|
||||||
|
RETURN
|
||||||
|
(
|
||||||
|
WITH RECURSIVE cte AS
|
||||||
|
(SELECT 1 as id UNION SELECT * FROM cte)
|
||||||
|
SELECT count(id) FROM cte
|
||||||
|
);
|
||||||
|
|
||||||
|
SELECT func();
|
||||||
|
|
||||||
|
DROP FUNCTION func;
|
||||||
|
|
||||||
--echo # Start of 10.3 tests
|
--echo # Start of 10.3 tests
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
|
23
mysql-test/main/cte_recursive_not_embedded.result
Normal file
23
mysql-test/main/cte_recursive_not_embedded.result
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#
|
||||||
|
# MDEV-15151: function with recursive CTE using no base tables
|
||||||
|
# (duplicate of MDEV-16661)
|
||||||
|
#
|
||||||
|
connection default;
|
||||||
|
CREATE TABLE t1 (id int KEY);
|
||||||
|
INSERT INTO t1 VALUES (0), (1),(2);
|
||||||
|
CREATE OR REPLACE FUNCTION func() RETURNS int
|
||||||
|
RETURN
|
||||||
|
(
|
||||||
|
WITH recursive cte AS
|
||||||
|
(SELECT 1 a UNION SELECT cte.* FROM cte natural join t1)
|
||||||
|
SELECT * FROM cte limit 1
|
||||||
|
);
|
||||||
|
connect con1,localhost,root,,test;
|
||||||
|
SELECT func();
|
||||||
|
connect con2,localhost,root,,test;
|
||||||
|
disconnect con2;
|
||||||
|
connection con1;
|
||||||
|
disconnect con1;
|
||||||
|
connection default;
|
||||||
|
DROP FUNCTION func;
|
||||||
|
DROP TABLE t1;
|
42
mysql-test/main/cte_recursive_not_embedded.test
Normal file
42
mysql-test/main/cte_recursive_not_embedded.test
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
--source include/not_embedded.inc
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-15151: function with recursive CTE using no base tables
|
||||||
|
--echo # (duplicate of MDEV-16661)
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--connection default
|
||||||
|
|
||||||
|
CREATE TABLE t1 (id int KEY);
|
||||||
|
INSERT INTO t1 VALUES (0), (1),(2);
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION func() RETURNS int
|
||||||
|
RETURN
|
||||||
|
(
|
||||||
|
WITH recursive cte AS
|
||||||
|
(SELECT 1 a UNION SELECT cte.* FROM cte natural join t1)
|
||||||
|
SELECT * FROM cte limit 1
|
||||||
|
);
|
||||||
|
|
||||||
|
--connect (con1,localhost,root,,test)
|
||||||
|
|
||||||
|
--let $conid= `SELECT CONNECTION_ID()`
|
||||||
|
--send SELECT func()
|
||||||
|
|
||||||
|
--connect (con2,localhost,root,,test)
|
||||||
|
--disable_query_log
|
||||||
|
--eval KILL QUERY $conid
|
||||||
|
--enable_query_log
|
||||||
|
--disconnect con2
|
||||||
|
|
||||||
|
--disable_result_log
|
||||||
|
--connection con1
|
||||||
|
--error 0,ER_QUERY_INTERRUPTED
|
||||||
|
--reap
|
||||||
|
--disconnect con1
|
||||||
|
--enable_result_log
|
||||||
|
|
||||||
|
--connection default
|
||||||
|
|
||||||
|
DROP FUNCTION func;
|
||||||
|
DROP TABLE t1;
|
@ -297,7 +297,7 @@ json_quote('foo')
|
|||||||
show create table t1;
|
show create table t1;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
t1 CREATE TABLE `t1` (
|
t1 CREATE TABLE `t1` (
|
||||||
`json_quote('foo')` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL
|
`json_quote('foo')` varchar(38) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
drop table t1;
|
drop table t1;
|
||||||
select json_merge('string');
|
select json_merge('string');
|
||||||
@ -748,6 +748,19 @@ SELECT * FROM t1 WHERE c IN (JSON_EXTRACT('{"a":"b"}', '$.*'));
|
|||||||
c
|
c
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
|
# MDEV-16814 CREATE TABLE SELECT JSON_QUOTE(multibyte_charset_expr) makes a field of a wrong length
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 AS SELECT
|
||||||
|
JSON_QUOTE(_latin1'foo') AS c1,
|
||||||
|
JSON_QUOTE(_utf8'foo') AS c2;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`c1` varchar(38) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
|
||||||
|
`c2` varchar(38) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
# End of 10.2 tests
|
# End of 10.2 tests
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -412,6 +412,16 @@ INSERT INTO t1 VALUES ('foo'),('bar');
|
|||||||
SELECT * FROM t1 WHERE c IN (JSON_EXTRACT('{"a":"b"}', '$.*'));
|
SELECT * FROM t1 WHERE c IN (JSON_EXTRACT('{"a":"b"}', '$.*'));
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-16814 CREATE TABLE SELECT JSON_QUOTE(multibyte_charset_expr) makes a field of a wrong length
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 AS SELECT
|
||||||
|
JSON_QUOTE(_latin1'foo') AS c1,
|
||||||
|
JSON_QUOTE(_utf8'foo') AS c2;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.2 tests
|
--echo # End of 10.2 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
@ -20,7 +20,7 @@ t1 CREATE TABLE `t1` (
|
|||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
insert t1 values ('[]');
|
insert t1 values ('[]');
|
||||||
insert t1 values ('a');
|
insert t1 values ('a');
|
||||||
ERROR 23000: CONSTRAINT `a` failed for `test`.`t1`
|
ERROR 23000: CONSTRAINT `t1.a` failed for `test`.`t1`
|
||||||
set timestamp=unix_timestamp('2010:11:12 13:14:15');
|
set timestamp=unix_timestamp('2010:11:12 13:14:15');
|
||||||
create or replace table t1(a json default(json_object('now', now())));
|
create or replace table t1(a json default(json_object('now', now())));
|
||||||
show create table t1;
|
show create table t1;
|
||||||
|
@ -296,20 +296,21 @@ DROP TABLE t1;
|
|||||||
# ASSERTION THD->TRANSACTION.XID_STATE.XID.IS_NULL()
|
# ASSERTION THD->TRANSACTION.XID_STATE.XID.IS_NULL()
|
||||||
# FAILED
|
# FAILED
|
||||||
#
|
#
|
||||||
DROP TABLE IF EXISTS t1, t2;
|
|
||||||
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
|
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
|
||||||
CREATE TABLE t2 (a INT) ENGINE=InnoDB;
|
CREATE TABLE t2 (a INT) ENGINE=InnoDB;
|
||||||
START TRANSACTION;
|
INSERT INTO t2 VALUES (1);
|
||||||
INSERT INTO t1 VALUES (1);
|
COMMIT;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES (2);
|
||||||
|
UPDATE t2 SET a=a+1;
|
||||||
connect con2,localhost,root;
|
connect con2,localhost,root;
|
||||||
XA START 'xid1';
|
XA START 'xid1';
|
||||||
|
INSERT INTO t1 VALUES (1);
|
||||||
# Sending:
|
# Sending:
|
||||||
INSERT INTO t2 SELECT a FROM t1;
|
DELETE FROM t2;
|
||||||
connection default;
|
connection default;
|
||||||
# Waiting until INSERT ... is blocked
|
|
||||||
DELETE FROM t1;
|
DELETE FROM t1;
|
||||||
connection con2;
|
connection con2;
|
||||||
# Reaping: INSERT INTO t2 SELECT a FROM t1
|
|
||||||
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||||
XA COMMIT 'xid1';
|
XA COMMIT 'xid1';
|
||||||
ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected
|
ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected
|
||||||
|
@ -393,33 +393,30 @@ DROP TABLE t1;
|
|||||||
--echo # FAILED
|
--echo # FAILED
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
--disable_warnings
|
|
||||||
DROP TABLE IF EXISTS t1, t2;
|
|
||||||
--enable_warnings
|
|
||||||
|
|
||||||
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
|
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
|
||||||
CREATE TABLE t2 (a INT) ENGINE=InnoDB;
|
CREATE TABLE t2 (a INT) ENGINE=InnoDB;
|
||||||
|
|
||||||
START TRANSACTION;
|
INSERT INTO t2 VALUES (1); COMMIT;
|
||||||
INSERT INTO t1 VALUES (1);
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES (2);
|
||||||
|
UPDATE t2 SET a=a+1;
|
||||||
|
|
||||||
--connect (con2,localhost,root)
|
--connect (con2,localhost,root)
|
||||||
XA START 'xid1';
|
XA START 'xid1';
|
||||||
|
INSERT INTO t1 VALUES (1);
|
||||||
--echo # Sending:
|
--echo # Sending:
|
||||||
--send INSERT INTO t2 SELECT a FROM t1
|
--send DELETE FROM t2
|
||||||
|
|
||||||
--connection default
|
--connection default
|
||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
SELECT COUNT(*) = 1 FROM information_schema.processlist
|
||||||
WHERE state = "Sending data"
|
WHERE state = "Updating"
|
||||||
AND info = "INSERT INTO t2 SELECT a FROM t1";
|
AND info = "DELETE FROM t2";
|
||||||
--echo # Waiting until INSERT ... is blocked
|
|
||||||
--source include/wait_condition.inc
|
--source include/wait_condition.inc
|
||||||
--sleep 0.1
|
--sleep 0.1
|
||||||
DELETE FROM t1;
|
--send DELETE FROM t1
|
||||||
|
|
||||||
--connection con2
|
--connection con2
|
||||||
--echo # Reaping: INSERT INTO t2 SELECT a FROM t1
|
|
||||||
--error ER_LOCK_DEADLOCK
|
--error ER_LOCK_DEADLOCK
|
||||||
--reap
|
--reap
|
||||||
--error ER_XA_RBDEADLOCK
|
--error ER_XA_RBDEADLOCK
|
||||||
@ -427,6 +424,7 @@ XA COMMIT 'xid1';
|
|||||||
|
|
||||||
connection default;
|
connection default;
|
||||||
|
|
||||||
|
reap;
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
connection con2;
|
connection con2;
|
||||||
|
@ -175,8 +175,38 @@ SET DEBUG_SYNC='now WAIT_FOR halfway';
|
|||||||
COMMIT;
|
COMMIT;
|
||||||
InnoDB 0 transactions not purged
|
InnoDB 0 transactions not purged
|
||||||
SET DEBUG_SYNC='now SIGNAL purged';
|
SET DEBUG_SYNC='now SIGNAL purged';
|
||||||
disconnect prevent_purge;
|
|
||||||
connection default;
|
connection default;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (y YEAR, vy YEAR AS (y) VIRTUAL UNIQUE, pk INT PRIMARY KEY)
|
||||||
|
ENGINE=InnoDB;
|
||||||
|
INSERT INTO t1 (pk,y) VALUES (1,2022);
|
||||||
|
CREATE TABLE t2(f1 INT NOT NULL, PRIMARY KEY(f1))ENGINE=InnoDB;
|
||||||
|
SET GLOBAL debug_dbug = '+d,ib_purge_virtual_index_callback';
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2(f1) VALUES(1);
|
||||||
|
connection prevent_purge;
|
||||||
|
SET DEBUG_SYNC=RESET;
|
||||||
|
start transaction with consistent snapshot;
|
||||||
|
connection default;
|
||||||
|
COMMIT;
|
||||||
|
connect truncate,localhost,root,,;
|
||||||
|
REPLACE INTO t1(pk, y) SELECT pk,y FROM t1;
|
||||||
|
SET DEBUG_SYNC='row_trunc_before_dict_lock SIGNAL commit WAIT_FOR release';
|
||||||
|
TRUNCATE TABLE t1;
|
||||||
|
connection prevent_purge;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR commit';
|
||||||
|
COMMIT;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL purge_start';
|
||||||
|
disconnect prevent_purge;
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR purge_start';
|
||||||
|
InnoDB 2 transactions not purged
|
||||||
|
SET DEBUG_SYNC='now SIGNAL release';
|
||||||
|
SET GLOBAL debug_dbug=@old_dbug;
|
||||||
|
connection truncate;
|
||||||
|
disconnect truncate;
|
||||||
|
connection default;
|
||||||
|
InnoDB 0 transactions not purged
|
||||||
|
DROP TABLE t1, t2;
|
||||||
set debug_sync=reset;
|
set debug_sync=reset;
|
||||||
SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;
|
SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;
|
||||||
|
@ -124,7 +124,7 @@ SELECT * FROM t1;
|
|||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
# Test adding virutal index on existing virtual column
|
# Test adding index on existing virtual column
|
||||||
CREATE TABLE t1 (a INT, b INT, c INT GENERATED ALWAYS AS(a+b));
|
CREATE TABLE t1 (a INT, b INT, c INT GENERATED ALWAYS AS(a+b));
|
||||||
|
|
||||||
INSERT INTO t1(a, b) VALUES (1, 1), (2, 2), (3, 3), (4, 4);
|
INSERT INTO t1(a, b) VALUES (1, 1), (2, 2), (3, 3), (4, 4);
|
||||||
@ -156,7 +156,9 @@ INSERT INTO t1(a, b) VALUES (8, 8);
|
|||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
--echo # wait for purge to process the deleted/updated records.
|
--echo # wait for purge to process the deleted/updated records.
|
||||||
|
let $wait_all_purged=2;
|
||||||
--source ../../innodb/include/wait_all_purged.inc
|
--source ../../innodb/include/wait_all_purged.inc
|
||||||
|
let $wait_all_purged=0;
|
||||||
|
|
||||||
SET DEBUG_SYNC= 'now SIGNAL purged';
|
SET DEBUG_SYNC= 'now SIGNAL purged';
|
||||||
|
|
||||||
@ -215,12 +217,54 @@ SET DEBUG_SYNC='now WAIT_FOR halfway';
|
|||||||
COMMIT;
|
COMMIT;
|
||||||
--source ../../innodb/include/wait_all_purged.inc
|
--source ../../innodb/include/wait_all_purged.inc
|
||||||
SET DEBUG_SYNC='now SIGNAL purged';
|
SET DEBUG_SYNC='now SIGNAL purged';
|
||||||
disconnect prevent_purge;
|
|
||||||
|
|
||||||
connection default;
|
connection default;
|
||||||
reap;
|
reap;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (y YEAR, vy YEAR AS (y) VIRTUAL UNIQUE, pk INT PRIMARY KEY)
|
||||||
|
ENGINE=InnoDB;
|
||||||
|
|
||||||
|
INSERT INTO t1 (pk,y) VALUES (1,2022);
|
||||||
|
CREATE TABLE t2(f1 INT NOT NULL, PRIMARY KEY(f1))ENGINE=InnoDB;
|
||||||
|
|
||||||
|
SET GLOBAL debug_dbug = '+d,ib_purge_virtual_index_callback';
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2(f1) VALUES(1);
|
||||||
|
connection prevent_purge;
|
||||||
|
SET DEBUG_SYNC=RESET;
|
||||||
|
start transaction with consistent snapshot;
|
||||||
|
connection default;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
connect(truncate,localhost,root,,);
|
||||||
|
REPLACE INTO t1(pk, y) SELECT pk,y FROM t1;
|
||||||
|
SET DEBUG_SYNC='row_trunc_before_dict_lock SIGNAL commit WAIT_FOR release';
|
||||||
|
send TRUNCATE TABLE t1;
|
||||||
|
|
||||||
|
connection prevent_purge;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR commit';
|
||||||
|
COMMIT;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL purge_start';
|
||||||
|
disconnect prevent_purge;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
SET DEBUG_SYNC='now WAIT_FOR purge_start';
|
||||||
|
let $wait_all_purged=2;
|
||||||
|
--source ../../innodb/include/wait_all_purged.inc
|
||||||
|
let $wait_all_purged=0;
|
||||||
|
SET DEBUG_SYNC='now SIGNAL release';
|
||||||
|
SET GLOBAL debug_dbug=@old_dbug;
|
||||||
|
|
||||||
|
connection truncate;
|
||||||
|
reap;
|
||||||
|
disconnect truncate;
|
||||||
|
|
||||||
|
connection default;
|
||||||
|
--source ../../innodb/include/wait_all_purged.inc
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
--source include/wait_until_count_sessions.inc
|
--source include/wait_until_count_sessions.inc
|
||||||
set debug_sync=reset;
|
set debug_sync=reset;
|
||||||
SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;
|
SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
# Wait for everything to be purged.
|
# Wait for everything to be purged.
|
||||||
# The user should have set innodb_purge_rseg_truncate_frequency=1.
|
# The user should have set innodb_purge_rseg_truncate_frequency=1.
|
||||||
|
|
||||||
|
if (!$wait_all_purged)
|
||||||
|
{
|
||||||
|
let $wait_all_purged= 0;
|
||||||
|
}
|
||||||
|
let $remaining_expect= `select concat('InnoDB ',$wait_all_purged)`;
|
||||||
|
|
||||||
let $wait_counter= 300;
|
let $wait_counter= 300;
|
||||||
while ($wait_counter)
|
while ($wait_counter)
|
||||||
{
|
{
|
||||||
--replace_regex /.*History list length ([0-9]+).*/\1/
|
--replace_regex /.*History list length ([0-9]+).*/\1/
|
||||||
let $remaining= `SHOW ENGINE INNODB STATUS`;
|
let $remaining= `SHOW ENGINE INNODB STATUS`;
|
||||||
if ($remaining == 'InnoDB 0')
|
if ($remaining == $remaining_expect)
|
||||||
{
|
{
|
||||||
let $wait_counter= 0;
|
let $wait_counter= 0;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ trx_last_foreign_key_error varchar(256) YES NULL
|
|||||||
trx_is_read_only int(1) NO 0
|
trx_is_read_only int(1) NO 0
|
||||||
trx_autocommit_non_locking int(1) NO 0
|
trx_autocommit_non_locking int(1) NO 0
|
||||||
trx_state trx_weight trx_tables_in_use trx_tables_locked trx_rows_locked trx_rows_modified trx_concurrency_tickets trx_isolation_level trx_unique_checks trx_foreign_key_checks
|
trx_state trx_weight trx_tables_in_use trx_tables_locked trx_rows_locked trx_rows_modified trx_concurrency_tickets trx_isolation_level trx_unique_checks trx_foreign_key_checks
|
||||||
RUNNING 4 0 1 7 1 0 REPEATABLE READ 1 1
|
RUNNING 3 0 1 5 1 0 REPEATABLE READ 1 1
|
||||||
trx_isolation_level trx_unique_checks trx_foreign_key_checks
|
trx_isolation_level trx_unique_checks trx_foreign_key_checks
|
||||||
SERIALIZABLE 0 0
|
SERIALIZABLE 0 0
|
||||||
trx_state trx_isolation_level trx_last_foreign_key_error
|
trx_state trx_isolation_level trx_last_foreign_key_error
|
||||||
|
@ -661,7 +661,21 @@ SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME
|
|||||||
LIKE 'buffer_page_written_index_leaf';
|
LIKE 'buffer_page_written_index_leaf';
|
||||||
NAME COUNT > 0
|
NAME COUNT > 0
|
||||||
buffer_page_written_index_leaf 1
|
buffer_page_written_index_leaf 1
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1(id INT PRIMARY KEY, a INT, b CHAR(1), UNIQUE KEY u(a,b))
|
||||||
|
ENGINE=InnoDB;
|
||||||
|
SET @start = (SELECT COUNT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME
|
||||||
|
= 'lock_rec_lock_created');
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t1 VALUES(1,1,'a'),(2,9999,'b'),(3,10000,'c'),(4,4,'d');
|
||||||
|
DELETE FROM t1 WHERE a = 9999 AND b='b';
|
||||||
|
COMMIT;
|
||||||
|
SET @end = (SELECT COUNT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME
|
||||||
|
= 'lock_rec_lock_created');
|
||||||
|
SELECT @end - @start;
|
||||||
|
@end - @start
|
||||||
|
0
|
||||||
|
DROP TABLE t1;
|
||||||
SET GLOBAL innodb_monitor_enable=default;
|
SET GLOBAL innodb_monitor_enable=default;
|
||||||
SET GLOBAL innodb_monitor_disable=default;
|
SET GLOBAL innodb_monitor_disable=default;
|
||||||
SET GLOBAL innodb_monitor_reset_all=default;
|
SET GLOBAL innodb_monitor_reset_all=default;
|
||||||
DROP TABLE t1;
|
|
||||||
|
@ -192,25 +192,9 @@ ROLLBACK;
|
|||||||
disconnect stop_purge;
|
disconnect stop_purge;
|
||||||
|
|
||||||
# Wait for purge to empty the table.
|
# Wait for purge to empty the table.
|
||||||
# (This is based on wait_all_purged.inc, but there are 2 transactions
|
let $wait_all_purged=2;
|
||||||
# from the pending ALTER TABLE t1 FORCE.)
|
--source include/wait_all_purged.inc
|
||||||
|
let $wait_all_purged=0;
|
||||||
let $wait_counter= 300;
|
|
||||||
while ($wait_counter)
|
|
||||||
{
|
|
||||||
--replace_regex /.*History list length ([0-9]+).*/\1/
|
|
||||||
let $remaining= `SHOW ENGINE INNODB STATUS`;
|
|
||||||
if ($remaining == 'InnoDB 2')
|
|
||||||
{
|
|
||||||
let $wait_counter= 0;
|
|
||||||
}
|
|
||||||
if ($wait_counter)
|
|
||||||
{
|
|
||||||
real_sleep 0.1;
|
|
||||||
dec $wait_counter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
echo $remaining transactions not purged;
|
|
||||||
|
|
||||||
SET DEBUG_SYNC='now SIGNAL logged';
|
SET DEBUG_SYNC='now SIGNAL logged';
|
||||||
disconnect ddl;
|
disconnect ddl;
|
||||||
|
@ -422,10 +422,27 @@ UNLOCK TABLES;
|
|||||||
SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME
|
SELECT NAME, COUNT > 0 FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME
|
||||||
LIKE 'buffer_page_written_index_leaf';
|
LIKE 'buffer_page_written_index_leaf';
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1(id INT PRIMARY KEY, a INT, b CHAR(1), UNIQUE KEY u(a,b))
|
||||||
|
ENGINE=InnoDB;
|
||||||
|
|
||||||
|
SET @start = (SELECT COUNT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME
|
||||||
|
= 'lock_rec_lock_created');
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t1 VALUES(1,1,'a'),(2,9999,'b'),(3,10000,'c'),(4,4,'d');
|
||||||
|
DELETE FROM t1 WHERE a = 9999 AND b='b';
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
SET @end = (SELECT COUNT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME
|
||||||
|
= 'lock_rec_lock_created');
|
||||||
|
SELECT @end - @start;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
SET GLOBAL innodb_monitor_enable=default;
|
SET GLOBAL innodb_monitor_enable=default;
|
||||||
SET GLOBAL innodb_monitor_disable=default;
|
SET GLOBAL innodb_monitor_disable=default;
|
||||||
SET GLOBAL innodb_monitor_reset_all=default;
|
SET GLOBAL innodb_monitor_reset_all=default;
|
||||||
--enable_warnings
|
--enable_warnings
|
||||||
|
|
||||||
DROP TABLE t1;
|
|
||||||
|
@ -2,6 +2,7 @@ call mtr.add_suppression("InnoDB: New log files created");
|
|||||||
CREATE TABLE t(i INT) ENGINE INNODB ENCRYPTED=YES;
|
CREATE TABLE t(i INT) ENGINE INNODB ENCRYPTED=YES;
|
||||||
INSERT INTO t VALUES(1);
|
INSERT INTO t VALUES(1);
|
||||||
# Create full backup , modify table, then create incremental/differential backup
|
# Create full backup , modify table, then create incremental/differential backup
|
||||||
|
SET GLOBAL innodb_flush_log_at_trx_commit = 1;
|
||||||
INSERT INTO t VALUES(2);
|
INSERT INTO t VALUES(2);
|
||||||
SELECT * FROM t;
|
SELECT * FROM t;
|
||||||
i
|
i
|
||||||
|
@ -20,6 +20,7 @@ echo # Create full backup , modify table, then create incremental/differential b
|
|||||||
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir;
|
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir;
|
||||||
--enable_result_log
|
--enable_result_log
|
||||||
|
|
||||||
|
SET GLOBAL innodb_flush_log_at_trx_commit = 1;
|
||||||
INSERT INTO t VALUES(2);
|
INSERT INTO t VALUES(2);
|
||||||
SELECT * FROM t;
|
SELECT * FROM t;
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
--innodb --loose-changed_page_bitmaps --innodb-sys-tables
|
--innodb --loose-changed_page_bitmaps --innodb-sys-tables --innodb-flush-log-at-trx-commit=2
|
||||||
|
@ -5,9 +5,6 @@ call mtr.add_suppression("InnoDB: If you are installing InnoDB, remember that yo
|
|||||||
call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`\\.`t21` because it could not be opened");
|
call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`\\.`t21` because it could not be opened");
|
||||||
call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: ");
|
call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: ");
|
||||||
call mtr.add_suppression("Table .* in the InnoDB data dictionary has tablespace id .*, but tablespace with that id or name does not exist");
|
call mtr.add_suppression("Table .* in the InnoDB data dictionary has tablespace id .*, but tablespace with that id or name does not exist");
|
||||||
SELECT @@GLOBAL.innodb_flush_log_at_trx_commit;
|
|
||||||
@@GLOBAL.innodb_flush_log_at_trx_commit
|
|
||||||
1
|
|
||||||
CREATE TABLE t1(i INT PRIMARY KEY auto_increment, a int) ENGINE INNODB;
|
CREATE TABLE t1(i INT PRIMARY KEY auto_increment, a int) ENGINE INNODB;
|
||||||
ALTER TABLE t1 FORCE, ALGORITHM=INPLACE;
|
ALTER TABLE t1 FORCE, ALGORITHM=INPLACE;
|
||||||
# Fails during full backup
|
# Fails during full backup
|
||||||
|
@ -10,7 +10,6 @@ call mtr.add_suppression("Table .* in the InnoDB data dictionary has tablespace
|
|||||||
let $basedir=$MYSQLTEST_VARDIR/tmp/backup;
|
let $basedir=$MYSQLTEST_VARDIR/tmp/backup;
|
||||||
let $incremental_dir=$MYSQLTEST_VARDIR/tmp/backup_inc1;
|
let $incremental_dir=$MYSQLTEST_VARDIR/tmp/backup_inc1;
|
||||||
|
|
||||||
SELECT @@GLOBAL.innodb_flush_log_at_trx_commit;
|
|
||||||
CREATE TABLE t1(i INT PRIMARY KEY auto_increment, a int) ENGINE INNODB;
|
CREATE TABLE t1(i INT PRIMARY KEY auto_increment, a int) ENGINE INNODB;
|
||||||
--source ../../suite/innodb/include/no_checkpoint_start.inc
|
--source ../../suite/innodb/include/no_checkpoint_start.inc
|
||||||
ALTER TABLE t1 FORCE, ALGORITHM=INPLACE;
|
ALTER TABLE t1 FORCE, ALGORITHM=INPLACE;
|
||||||
|
@ -6,9 +6,16 @@ eval LOAD DATA INFILE '$LOAD_FILE' INTO TABLE t1;
|
|||||||
eval LOAD DATA INFILE '$LOAD_FILE' INTO TABLE t1;
|
eval LOAD DATA INFILE '$LOAD_FILE' INTO TABLE t1;
|
||||||
SELECT * FROM t1 ORDER BY word LIMIT 10;
|
SELECT * FROM t1 ORDER BY word LIMIT 10;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Save password row for root
|
||||||
|
#
|
||||||
|
|
||||||
|
create temporary table tmp select * from mysql.user where host="localhost" and user="root";
|
||||||
|
|
||||||
#
|
#
|
||||||
# Test slave with wrong password
|
# Test slave with wrong password
|
||||||
#
|
#
|
||||||
|
|
||||||
save_master_pos;
|
save_master_pos;
|
||||||
connection slave;
|
connection slave;
|
||||||
sync_with_master;
|
sync_with_master;
|
||||||
@ -24,6 +31,7 @@ connection master;
|
|||||||
real_sleep 2;
|
real_sleep 2;
|
||||||
SET PASSWORD FOR root@"localhost" = PASSWORD('');
|
SET PASSWORD FOR root@"localhost" = PASSWORD('');
|
||||||
# Give slave time to connect (will retry every second)
|
# Give slave time to connect (will retry every second)
|
||||||
|
|
||||||
sleep 2;
|
sleep 2;
|
||||||
|
|
||||||
CREATE TABLE t3(n INT);
|
CREATE TABLE t3(n INT);
|
||||||
@ -80,4 +88,9 @@ SELECT n FROM t1;
|
|||||||
|
|
||||||
connection master;
|
connection master;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
# resttore old passwords
|
||||||
|
replace into mysql.user select * from tmp;
|
||||||
|
drop temporary table tmp;
|
||||||
|
|
||||||
sync_slave_with_master;
|
sync_slave_with_master;
|
||||||
|
9
mysql-test/suite/rpl/r/rpl_15867.result
Normal file
9
mysql-test/suite/rpl/r/rpl_15867.result
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
include/master-slave.inc
|
||||||
|
[connection master]
|
||||||
|
CREATE TEMPORARY TABLE t (i INT);
|
||||||
|
CREATE TABLE t AS SELECT * FROM t;
|
||||||
|
connection slave;
|
||||||
|
connection master;
|
||||||
|
DROP TEMPORARY TABLE t;
|
||||||
|
DROP TABLE t;
|
||||||
|
include/rpl_end.inc
|
@ -15,6 +15,7 @@ Aaron
|
|||||||
Aaron
|
Aaron
|
||||||
Ababa
|
Ababa
|
||||||
Ababa
|
Ababa
|
||||||
|
create temporary table tmp select * from mysql.user where host="localhost" and user="root";
|
||||||
connection slave;
|
connection slave;
|
||||||
STOP SLAVE;
|
STOP SLAVE;
|
||||||
connection master;
|
connection master;
|
||||||
@ -65,5 +66,7 @@ n
|
|||||||
3456
|
3456
|
||||||
connection master;
|
connection master;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
replace into mysql.user select * from tmp;
|
||||||
|
drop temporary table tmp;
|
||||||
connection slave;
|
connection slave;
|
||||||
include/rpl_end.inc
|
include/rpl_end.inc
|
||||||
|
11
mysql-test/suite/rpl/t/rpl_15867.test
Normal file
11
mysql-test/suite/rpl/t/rpl_15867.test
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
--source include/master-slave.inc
|
||||||
|
CREATE TEMPORARY TABLE t (i INT);
|
||||||
|
CREATE TABLE t AS SELECT * FROM t;
|
||||||
|
|
||||||
|
--sync_slave_with_master
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
--connection master
|
||||||
|
DROP TEMPORARY TABLE t;
|
||||||
|
DROP TABLE t;
|
||||||
|
--source include/rpl_end.inc
|
@ -1326,9 +1326,9 @@ READ_ONLY YES
|
|||||||
COMMAND_LINE_ARGUMENT NONE
|
COMMAND_LINE_ARGUMENT NONE
|
||||||
VARIABLE_NAME INNODB_LOCK_SCHEDULE_ALGORITHM
|
VARIABLE_NAME INNODB_LOCK_SCHEDULE_ALGORITHM
|
||||||
SESSION_VALUE NULL
|
SESSION_VALUE NULL
|
||||||
GLOBAL_VALUE vats
|
GLOBAL_VALUE fcfs
|
||||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||||
DEFAULT_VALUE vats
|
DEFAULT_VALUE fcfs
|
||||||
VARIABLE_SCOPE GLOBAL
|
VARIABLE_SCOPE GLOBAL
|
||||||
VARIABLE_TYPE ENUM
|
VARIABLE_TYPE ENUM
|
||||||
VARIABLE_COMMENT The algorithm Innodb uses for deciding which locks to grant next when a lock is released. Possible values are FCFS grant the locks in First-Come-First-Served order; VATS use the Variance-Aware-Transaction-Scheduling algorithm, which uses an Eldest-Transaction-First heuristic.
|
VARIABLE_COMMENT The algorithm Innodb uses for deciding which locks to grant next when a lock is released. Possible values are FCFS grant the locks in First-Come-First-Served order; VATS use the Variance-Aware-Transaction-Scheduling algorithm, which uses an Eldest-Transaction-First heuristic.
|
||||||
|
@ -7755,10 +7755,9 @@ void Field_varstring::sql_type(String &res) const
|
|||||||
size_t length;
|
size_t length;
|
||||||
|
|
||||||
length= cs->cset->snprintf(cs,(char*) res.ptr(),
|
length= cs->cset->snprintf(cs,(char*) res.ptr(),
|
||||||
res.alloced_length(), "%s(%d)",
|
res.alloced_length(), "%s(%u)",
|
||||||
(has_charset() ? "varchar" : "varbinary"),
|
(has_charset() ? "varchar" : "varbinary"),
|
||||||
(int) field_length / charset()->mbmaxlen -
|
(uint) char_length());
|
||||||
MY_TEST(compression_method()));
|
|
||||||
res.length(length);
|
res.length(length);
|
||||||
if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
|
if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
|
||||||
has_charset() && (charset()->state & MY_CS_BINSORT))
|
has_charset() && (charset()->state & MY_CS_BINSORT))
|
||||||
|
@ -575,7 +575,7 @@ bool Item_func_json_quote::fix_length_and_dec()
|
|||||||
Odd but realistic worst case is when all characters
|
Odd but realistic worst case is when all characters
|
||||||
of the argument turn into '\uXXXX\uXXXX', which is 12.
|
of the argument turn into '\uXXXX\uXXXX', which is 12.
|
||||||
*/
|
*/
|
||||||
max_length= args[0]->max_length * 12 + 2;
|
fix_char_length_ulonglong((ulonglong) args[0]->max_char_length() * 12 + 2);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "sql_array.h" // Dynamic_array
|
#include "sql_array.h" // Dynamic_array
|
||||||
#include "log_event.h" // Query_log_event
|
#include "log_event.h" // Query_log_event
|
||||||
#include "sql_derived.h" // mysql_handle_derived
|
#include "sql_derived.h" // mysql_handle_derived
|
||||||
|
#include "sql_cte.h"
|
||||||
#include "sql_select.h" // Virtual_tmp_table
|
#include "sql_select.h" // Virtual_tmp_table
|
||||||
|
|
||||||
#ifdef USE_PRAGMA_IMPLEMENTATION
|
#ifdef USE_PRAGMA_IMPLEMENTATION
|
||||||
@ -3287,7 +3288,8 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (open_tables)
|
if (open_tables)
|
||||||
res= instr->exec_open_and_lock_tables(thd, m_lex->query_tables);
|
res= check_dependencies_in_with_clauses(m_lex->with_clauses_list) ||
|
||||||
|
instr->exec_open_and_lock_tables(thd, m_lex->query_tables);
|
||||||
|
|
||||||
if (likely(!res))
|
if (likely(!res))
|
||||||
{
|
{
|
||||||
|
@ -1039,6 +1039,12 @@ retry:
|
|||||||
if (res->table && (res->table == table->table))
|
if (res->table && (res->table == table->table))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Skip if table is tmp table */
|
||||||
|
if (check_flag & CHECK_DUP_SKIP_TEMP_TABLE &&
|
||||||
|
res->table && res->table->s->tmp_table != NO_TMP_TABLE)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (check_flag & CHECK_DUP_FOR_CREATE)
|
if (check_flag & CHECK_DUP_FOR_CREATE)
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
|
|||||||
/* Flag bits for unique_table() */
|
/* Flag bits for unique_table() */
|
||||||
#define CHECK_DUP_ALLOW_DIFFERENT_ALIAS 1
|
#define CHECK_DUP_ALLOW_DIFFERENT_ALIAS 1
|
||||||
#define CHECK_DUP_FOR_CREATE 2
|
#define CHECK_DUP_FOR_CREATE 2
|
||||||
|
#define CHECK_DUP_SKIP_TEMP_TABLE 4
|
||||||
|
|
||||||
uint get_table_def_key(const TABLE_LIST *table_list, const char **key);
|
uint get_table_def_key(const TABLE_LIST *table_list, const char **key);
|
||||||
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
|
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
|
||||||
|
@ -4677,13 +4677,6 @@ TABLE *open_purge_table(THD *thd, const char *db, size_t dblen,
|
|||||||
DBUG_RETURN(error ? NULL : tl->table);
|
DBUG_RETURN(error ? NULL : tl->table);
|
||||||
}
|
}
|
||||||
|
|
||||||
TABLE *get_purge_table(THD *thd)
|
|
||||||
{
|
|
||||||
/* see above, at most one table can be opened */
|
|
||||||
DBUG_ASSERT(thd->open_tables == NULL || thd->open_tables->next == NULL);
|
|
||||||
return thd->open_tables;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Find an open table in the list of prelocked tabled
|
/** Find an open table in the list of prelocked tabled
|
||||||
|
|
||||||
|
@ -4199,7 +4199,8 @@ mysql_execute_command(THD *thd)
|
|||||||
TABLE_LIST *duplicate;
|
TABLE_LIST *duplicate;
|
||||||
if (unlikely((duplicate= unique_table(thd, lex->query_tables,
|
if (unlikely((duplicate= unique_table(thd, lex->query_tables,
|
||||||
lex->query_tables->next_global,
|
lex->query_tables->next_global,
|
||||||
CHECK_DUP_FOR_CREATE))))
|
CHECK_DUP_FOR_CREATE |
|
||||||
|
CHECK_DUP_SKIP_TEMP_TABLE))))
|
||||||
{
|
{
|
||||||
update_non_unique_table_error(lex->query_tables, "CREATE",
|
update_non_unique_table_error(lex->query_tables, "CREATE",
|
||||||
duplicate);
|
duplicate);
|
||||||
|
12
sql/table.cc
12
sql/table.cc
@ -5275,8 +5275,18 @@ int TABLE::verify_constraints(bool ignore_failure)
|
|||||||
if (((*chk)->expr->val_int() == 0 && !(*chk)->expr->null_value) ||
|
if (((*chk)->expr->val_int() == 0 && !(*chk)->expr->null_value) ||
|
||||||
in_use->is_error())
|
in_use->is_error())
|
||||||
{
|
{
|
||||||
|
StringBuffer<MAX_FIELD_WIDTH> field_error(system_charset_info);
|
||||||
|
enum_vcol_info_type vcol_type= (*chk)->get_vcol_type();
|
||||||
|
DBUG_ASSERT(vcol_type == VCOL_CHECK_TABLE ||
|
||||||
|
vcol_type == VCOL_CHECK_FIELD);
|
||||||
|
if (vcol_type == VCOL_CHECK_FIELD)
|
||||||
|
{
|
||||||
|
field_error.append(s->table_name.str);
|
||||||
|
field_error.append(".");
|
||||||
|
}
|
||||||
|
field_error.append((*chk)->name.str);
|
||||||
my_error(ER_CONSTRAINT_FAILED,
|
my_error(ER_CONSTRAINT_FAILED,
|
||||||
MYF(ignore_failure ? ME_WARNING : 0), (*chk)->name.str,
|
MYF(ignore_failure ? ME_WARNING : 0), field_error.c_ptr(),
|
||||||
s->db.str, s->error_table_name());
|
s->db.str, s->error_table_name());
|
||||||
return ignore_failure ? VIEW_CHECK_SKIP : VIEW_CHECK_ERROR;
|
return ignore_failure ? VIEW_CHECK_SKIP : VIEW_CHECK_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -570,10 +570,9 @@ static
|
|||||||
bool
|
bool
|
||||||
btr_search_update_block_hash_info(btr_search_t* info, buf_block_t* block)
|
btr_search_update_block_hash_info(btr_search_t* info, buf_block_t* block)
|
||||||
{
|
{
|
||||||
ut_ad(!btr_search_own_any(RW_LOCK_S));
|
ut_ad(!btr_search_own_any());
|
||||||
ut_ad(!btr_search_own_any(RW_LOCK_X));
|
ut_ad(rw_lock_own_flagged(&block->lock,
|
||||||
ut_ad(rw_lock_own(&block->lock, RW_LOCK_S)
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
|| rw_lock_own(&block->lock, RW_LOCK_X));
|
|
||||||
|
|
||||||
info->last_hash_succ = FALSE;
|
info->last_hash_succ = FALSE;
|
||||||
|
|
||||||
@ -648,8 +647,8 @@ btr_search_update_hash_ref(
|
|||||||
|
|
||||||
ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
|
ut_ad(cursor->flag == BTR_CUR_HASH_FAIL);
|
||||||
ut_ad(rw_lock_own(btr_get_search_latch(cursor->index), RW_LOCK_X));
|
ut_ad(rw_lock_own(btr_get_search_latch(cursor->index), RW_LOCK_X));
|
||||||
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_S)
|
ut_ad(rw_lock_own_flagged(&block->lock,
|
||||||
|| rw_lock_own(&(block->lock), RW_LOCK_X));
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
ut_ad(page_align(btr_cur_get_rec(cursor)) == block->frame);
|
ut_ad(page_align(btr_cur_get_rec(cursor)) == block->frame);
|
||||||
ut_ad(page_is_leaf(block->frame));
|
ut_ad(page_is_leaf(block->frame));
|
||||||
assert_block_ahi_valid(block);
|
assert_block_ahi_valid(block);
|
||||||
@ -887,8 +886,8 @@ btr_search_guess_on_hash(
|
|||||||
btr_cur_t cursor2;
|
btr_cur_t cursor2;
|
||||||
btr_pcur_t pcur;
|
btr_pcur_t pcur;
|
||||||
#endif
|
#endif
|
||||||
ut_ad(!ahi_latch || rw_lock_own(ahi_latch, RW_LOCK_S)
|
ut_ad(!ahi_latch || rw_lock_own_flagged(
|
||||||
|| rw_lock_own(ahi_latch, RW_LOCK_X));
|
ahi_latch, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
|
|
||||||
if (!btr_search_enabled) {
|
if (!btr_search_enabled) {
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
@ -1109,8 +1108,8 @@ retry:
|
|||||||
|
|
||||||
ut_ad(block->page.buf_fix_count == 0
|
ut_ad(block->page.buf_fix_count == 0
|
||||||
|| buf_block_get_state(block) == BUF_BLOCK_REMOVE_HASH
|
|| buf_block_get_state(block) == BUF_BLOCK_REMOVE_HASH
|
||||||
|| rw_lock_own(&block->lock, RW_LOCK_S)
|
|| rw_lock_own_flagged(&block->lock,
|
||||||
|| rw_lock_own(&block->lock, RW_LOCK_X));
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
ut_ad(page_is_leaf(block->frame));
|
ut_ad(page_is_leaf(block->frame));
|
||||||
|
|
||||||
/* We must not dereference index here, because it could be freed
|
/* We must not dereference index here, because it could be freed
|
||||||
@ -1307,7 +1306,7 @@ void btr_search_drop_page_hash_when_freed(const page_id_t& page_id)
|
|||||||
/* In all our callers, the table handle should
|
/* In all our callers, the table handle should
|
||||||
be open, or we should be in the process of
|
be open, or we should be in the process of
|
||||||
dropping the table (preventing eviction). */
|
dropping the table (preventing eviction). */
|
||||||
ut_ad(index->table->n_ref_count > 0
|
ut_ad(index->table->get_ref_count() > 0
|
||||||
|| mutex_own(&dict_sys->mutex));
|
|| mutex_own(&dict_sys->mutex));
|
||||||
btr_search_drop_page_hash_index(block);
|
btr_search_drop_page_hash_index(block);
|
||||||
}
|
}
|
||||||
@ -1363,8 +1362,8 @@ btr_search_build_page_hash_index(
|
|||||||
ut_a(!dict_index_is_ibuf(index));
|
ut_a(!dict_index_is_ibuf(index));
|
||||||
ut_ad(page_is_leaf(block->frame));
|
ut_ad(page_is_leaf(block->frame));
|
||||||
|
|
||||||
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_S)
|
ut_ad(rw_lock_own_flagged(&block->lock,
|
||||||
|| rw_lock_own(&(block->lock), RW_LOCK_X));
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
|
|
||||||
rw_lock_s_lock(ahi_latch);
|
rw_lock_s_lock(ahi_latch);
|
||||||
|
|
||||||
@ -1531,8 +1530,8 @@ btr_search_info_update_slow(btr_search_t* info, btr_cur_t* cursor)
|
|||||||
{
|
{
|
||||||
rw_lock_t* ahi_latch = btr_get_search_latch(cursor->index);
|
rw_lock_t* ahi_latch = btr_get_search_latch(cursor->index);
|
||||||
|
|
||||||
ut_ad(!rw_lock_own(ahi_latch, RW_LOCK_S));
|
ut_ad(!rw_lock_own_flagged(ahi_latch,
|
||||||
ut_ad(!rw_lock_own(ahi_latch, RW_LOCK_X));
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
|
|
||||||
buf_block_t* block = btr_cur_get_block(cursor);
|
buf_block_t* block = btr_cur_get_block(cursor);
|
||||||
|
|
||||||
|
@ -4498,8 +4498,9 @@ loop:
|
|||||||
case BUF_GET_IF_IN_POOL_OR_WATCH:
|
case BUF_GET_IF_IN_POOL_OR_WATCH:
|
||||||
case BUF_PEEK_IF_IN_POOL:
|
case BUF_PEEK_IF_IN_POOL:
|
||||||
case BUF_EVICT_IF_IN_POOL:
|
case BUF_EVICT_IF_IN_POOL:
|
||||||
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_X));
|
ut_ad(!rw_lock_own_flagged(
|
||||||
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_S));
|
hash_lock,
|
||||||
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4840,8 +4841,8 @@ evict_from_pool:
|
|||||||
ut_ad(block == fix_block);
|
ut_ad(block == fix_block);
|
||||||
ut_ad(fix_block->page.buf_fix_count > 0);
|
ut_ad(fix_block->page.buf_fix_count > 0);
|
||||||
|
|
||||||
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_X));
|
ut_ad(!rw_lock_own_flagged(hash_lock,
|
||||||
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_S));
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
|
|
||||||
ut_ad(buf_block_get_state(fix_block) == BUF_BLOCK_FILE_PAGE);
|
ut_ad(buf_block_get_state(fix_block) == BUF_BLOCK_FILE_PAGE);
|
||||||
|
|
||||||
@ -5015,8 +5016,8 @@ evict_from_pool:
|
|||||||
ut_a(ibuf_count_get(fix_block->page.id) == 0);
|
ut_a(ibuf_count_get(fix_block->page.id) == 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_X));
|
ut_ad(!rw_lock_own_flagged(hash_lock,
|
||||||
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_S));
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
|
|
||||||
return(fix_block);
|
return(fix_block);
|
||||||
}
|
}
|
||||||
@ -5688,8 +5689,8 @@ func_exit:
|
|||||||
ibuf_mtr_commit(&mtr);
|
ibuf_mtr_commit(&mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_X));
|
ut_ad(!rw_lock_own_flagged(hash_lock,
|
||||||
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_S));
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
ut_ad(!bpage || buf_page_in_file(bpage));
|
ut_ad(!bpage || buf_page_in_file(bpage));
|
||||||
|
|
||||||
return(bpage);
|
return(bpage);
|
||||||
|
@ -967,7 +967,7 @@ buf_flush_init_for_writing(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t checksum= 0;
|
uint32_t checksum = BUF_NO_CHECKSUM_MAGIC;
|
||||||
|
|
||||||
switch (srv_checksum_algorithm_t(srv_checksum_algorithm)) {
|
switch (srv_checksum_algorithm_t(srv_checksum_algorithm)) {
|
||||||
case SRV_CHECKSUM_ALGORITHM_INNODB:
|
case SRV_CHECKSUM_ALGORITHM_INNODB:
|
||||||
@ -990,7 +990,6 @@ buf_flush_init_for_writing(
|
|||||||
break;
|
break;
|
||||||
case SRV_CHECKSUM_ALGORITHM_NONE:
|
case SRV_CHECKSUM_ALGORITHM_NONE:
|
||||||
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
|
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
|
||||||
checksum = BUF_NO_CHECKSUM_MAGIC;
|
|
||||||
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
|
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
|
||||||
checksum);
|
checksum);
|
||||||
break;
|
break;
|
||||||
|
@ -1629,8 +1629,8 @@ func_exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* buf_LRU_block_remove_hashed() releases the hash_lock */
|
/* buf_LRU_block_remove_hashed() releases the hash_lock */
|
||||||
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_X)
|
ut_ad(!rw_lock_own_flagged(hash_lock,
|
||||||
&& !rw_lock_own(hash_lock, RW_LOCK_S));
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
|
|
||||||
/* We have just freed a BUF_BLOCK_FILE_PAGE. If b != NULL
|
/* We have just freed a BUF_BLOCK_FILE_PAGE. If b != NULL
|
||||||
then it was a compressed page with an uncompressed frame and
|
then it was a compressed page with an uncompressed frame and
|
||||||
@ -2183,9 +2183,8 @@ buf_LRU_free_one_page(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* buf_LRU_block_remove_hashed() releases hash_lock and block_mutex */
|
/* buf_LRU_block_remove_hashed() releases hash_lock and block_mutex */
|
||||||
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_X)
|
ut_ad(!rw_lock_own_flagged(hash_lock,
|
||||||
&& !rw_lock_own(hash_lock, RW_LOCK_S));
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
|
|
||||||
ut_ad(!mutex_own(block_mutex));
|
ut_ad(!mutex_own(block_mutex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,7 +418,7 @@ dict_table_try_drop_aborted(
|
|||||||
dict_table_t* table, /*!< in: table, or NULL if it
|
dict_table_t* table, /*!< in: table, or NULL if it
|
||||||
needs to be looked up again */
|
needs to be looked up again */
|
||||||
table_id_t table_id, /*!< in: table identifier */
|
table_id_t table_id, /*!< in: table identifier */
|
||||||
ulint ref_count) /*!< in: expected table->n_ref_count */
|
int32 ref_count) /*!< in: expected table->n_ref_count */
|
||||||
{
|
{
|
||||||
trx_t* trx;
|
trx_t* trx;
|
||||||
|
|
||||||
@ -1328,7 +1328,7 @@ static
|
|||||||
ibool
|
ibool
|
||||||
dict_table_can_be_evicted(
|
dict_table_can_be_evicted(
|
||||||
/*======================*/
|
/*======================*/
|
||||||
const dict_table_t* table) /*!< in: table to test */
|
dict_table_t* table) /*!< in: table to test */
|
||||||
{
|
{
|
||||||
ut_ad(mutex_own(&dict_sys->mutex));
|
ut_ad(mutex_own(&dict_sys->mutex));
|
||||||
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
|
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
|
||||||
@ -6872,6 +6872,7 @@ dict_foreign_qualify_index(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (field->col->is_virtual()) {
|
if (field->col->is_virtual()) {
|
||||||
|
col_name = "";
|
||||||
for (ulint j = 0; j < table->n_v_def; j++) {
|
for (ulint j = 0; j < table->n_v_def; j++) {
|
||||||
col_name = dict_table_get_v_col_name(table, j);
|
col_name = dict_table_get_v_col_name(table, j);
|
||||||
if (innobase_strcasecmp(field->name,col_name) == 0) {
|
if (innobase_strcasecmp(field->name,col_name) == 0) {
|
||||||
|
@ -1479,7 +1479,6 @@ fil_space_create(
|
|||||||
rw_lock_create(fil_space_latch_key, &space->latch, SYNC_FSP);
|
rw_lock_create(fil_space_latch_key, &space->latch, SYNC_FSP);
|
||||||
|
|
||||||
if (space->purpose == FIL_TYPE_TEMPORARY) {
|
if (space->purpose == FIL_TYPE_TEMPORARY) {
|
||||||
ut_d(space->latch.set_temp_fsp());
|
|
||||||
/* SysTablespace::open_or_create() would pass
|
/* SysTablespace::open_or_create() would pass
|
||||||
size!=0 to fil_node_create(), so first_time_open
|
size!=0 to fil_node_create(), so first_time_open
|
||||||
would not hold in fil_node_open_file(), and we
|
would not hold in fil_node_open_file(), and we
|
||||||
|
@ -257,9 +257,8 @@ rtr_pcur_getnext_from_path(
|
|||||||
rtr_info->tree_savepoints[tree_idx] = mtr_set_savepoint(mtr);
|
rtr_info->tree_savepoints[tree_idx] = mtr_set_savepoint(mtr);
|
||||||
|
|
||||||
#ifdef UNIV_RTR_DEBUG
|
#ifdef UNIV_RTR_DEBUG
|
||||||
ut_ad(!(rw_lock_own(&btr_cur->page_cur.block->lock, RW_LOCK_X)
|
ut_ad(!(rw_lock_own_flagged(&btr_cur->page_cur.block->lock,
|
||||||
||
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S))
|
||||||
rw_lock_own(&btr_cur->page_cur.block->lock, RW_LOCK_S))
|
|
||||||
|| my_latch_mode == BTR_MODIFY_TREE
|
|| my_latch_mode == BTR_MODIFY_TREE
|
||||||
|| my_latch_mode == BTR_CONT_MODIFY_TREE
|
|| my_latch_mode == BTR_CONT_MODIFY_TREE
|
||||||
|| !page_is_leaf(buf_block_get_frame(
|
|| !page_is_leaf(buf_block_get_frame(
|
||||||
|
@ -128,7 +128,7 @@ void destroy_thd(MYSQL_THD thd);
|
|||||||
void reset_thd(MYSQL_THD thd);
|
void reset_thd(MYSQL_THD thd);
|
||||||
TABLE *open_purge_table(THD *thd, const char *db, size_t dblen,
|
TABLE *open_purge_table(THD *thd, const char *db, size_t dblen,
|
||||||
const char *tb, size_t tblen);
|
const char *tb, size_t tblen);
|
||||||
TABLE *get_purge_table(THD *thd);
|
void close_thread_tables(THD* thd);
|
||||||
|
|
||||||
#ifdef MYSQL_DYNAMIC_PLUGIN
|
#ifdef MYSQL_DYNAMIC_PLUGIN
|
||||||
#define tc_size 400
|
#define tc_size 400
|
||||||
@ -2969,7 +2969,7 @@ ha_innobase::update_thd(
|
|||||||
m_user_thd, thd));
|
m_user_thd, thd));
|
||||||
|
|
||||||
/* The table should have been opened in ha_innobase::open(). */
|
/* The table should have been opened in ha_innobase::open(). */
|
||||||
ut_ad(m_prebuilt->table->n_ref_count > 0);
|
DBUG_ASSERT(m_prebuilt->table->get_ref_count() > 0);
|
||||||
|
|
||||||
trx_t* trx = check_trx_exists(thd);
|
trx_t* trx = check_trx_exists(thd);
|
||||||
|
|
||||||
@ -13913,7 +13913,7 @@ ha_innobase::info_low(
|
|||||||
m_prebuilt->trx->op_info = "returning various info to MariaDB";
|
m_prebuilt->trx->op_info = "returning various info to MariaDB";
|
||||||
|
|
||||||
ib_table = m_prebuilt->table;
|
ib_table = m_prebuilt->table;
|
||||||
ut_ad(ib_table->n_ref_count > 0);
|
DBUG_ASSERT(ib_table->get_ref_count() > 0);
|
||||||
|
|
||||||
if (flag & HA_STATUS_TIME) {
|
if (flag & HA_STATUS_TIME) {
|
||||||
if (is_analyze || innobase_stats_on_metadata) {
|
if (is_analyze || innobase_stats_on_metadata) {
|
||||||
@ -19478,7 +19478,7 @@ static MYSQL_SYSVAR_ENUM(lock_schedule_algorithm, innodb_lock_schedule_algorithm
|
|||||||
" VATS"
|
" VATS"
|
||||||
" use the Variance-Aware-Transaction-Scheduling algorithm, which"
|
" use the Variance-Aware-Transaction-Scheduling algorithm, which"
|
||||||
" uses an Eldest-Transaction-First heuristic.",
|
" uses an Eldest-Transaction-First heuristic.",
|
||||||
NULL, NULL, INNODB_LOCK_SCHEDULE_ALGORITHM_VATS,
|
NULL, NULL, INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS,
|
||||||
&innodb_lock_schedule_algorithm_typelib);
|
&innodb_lock_schedule_algorithm_typelib);
|
||||||
|
|
||||||
static MYSQL_SYSVAR_ULONG(buffer_pool_instances, srv_buf_pool_instances,
|
static MYSQL_SYSVAR_ULONG(buffer_pool_instances, srv_buf_pool_instances,
|
||||||
@ -20618,63 +20618,151 @@ innobase_index_cond(
|
|||||||
return handler_index_cond_check(file);
|
return handler_index_cond_check(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Parse the table file name into table name and database name.
|
||||||
/** Find or open a mysql table for the virtual column template
|
@param[in] tbl_name InnoDB table name
|
||||||
@param[in] thd mysql thread handle
|
@param[out] dbname database name buffer (NAME_LEN + 1 bytes)
|
||||||
@param[in,out] table InnoDB table whose virtual column template is to be updated
|
@param[out] tblname table name buffer (NAME_LEN + 1 bytes)
|
||||||
@return TABLE if successful or NULL */
|
@param[out] dbnamelen database name length
|
||||||
static TABLE *
|
@param[out] tblnamelen table name length
|
||||||
innobase_find_mysql_table_for_vc(
|
@return true if the table name is parsed properly. */
|
||||||
/*=============================*/
|
static bool table_name_parse(
|
||||||
THD* thd,
|
const table_name_t& tbl_name,
|
||||||
dict_table_t* table)
|
char* dbname,
|
||||||
|
char* tblname,
|
||||||
|
ulint& dbnamelen,
|
||||||
|
ulint& tblnamelen)
|
||||||
{
|
{
|
||||||
TABLE *mysql_table;
|
dbnamelen = dict_get_db_name_len(tbl_name.m_name);
|
||||||
bool bg_thread = THDVAR(thd, background_thread);
|
char db_buf[MAX_DATABASE_NAME_LEN + 1];
|
||||||
|
char tbl_buf[MAX_TABLE_NAME_LEN + 1];
|
||||||
|
|
||||||
if (bg_thread) {
|
ut_ad(dbnamelen > 0);
|
||||||
if ((mysql_table = get_purge_table(thd))) {
|
ut_ad(dbnamelen <= MAX_DATABASE_NAME_LEN);
|
||||||
return mysql_table;
|
|
||||||
|
memcpy(db_buf, tbl_name.m_name, dbnamelen);
|
||||||
|
db_buf[dbnamelen] = 0;
|
||||||
|
|
||||||
|
tblnamelen = strlen(tbl_name.m_name + dbnamelen + 1);
|
||||||
|
memcpy(tbl_buf, tbl_name.m_name + dbnamelen + 1, tblnamelen);
|
||||||
|
tbl_buf[tblnamelen] = 0;
|
||||||
|
|
||||||
|
filename_to_tablename(db_buf, dbname, MAX_DATABASE_NAME_LEN + 1, true);
|
||||||
|
|
||||||
|
if (tblnamelen > TEMP_FILE_PREFIX_LENGTH
|
||||||
|
&& !strncmp(tbl_buf, TEMP_FILE_PREFIX, TEMP_FILE_PREFIX_LENGTH)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (char *is_part = strchr(tbl_buf, '#')) {
|
||||||
|
*is_part = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
filename_to_tablename(tbl_buf, tblname, MAX_TABLE_NAME_LEN + 1, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Acquire metadata lock and MariaDB table handle for an InnoDB table.
|
||||||
|
@param[in,out] thd thread handle
|
||||||
|
@param[in,out] table InnoDB table
|
||||||
|
@return MariaDB table handle
|
||||||
|
@retval NULL if the table does not exist, is unaccessible or corrupted. */
|
||||||
|
static TABLE* innodb_acquire_mdl(THD* thd, dict_table_t* table)
|
||||||
|
{
|
||||||
|
char db_buf[NAME_LEN + 1], db_buf1[NAME_LEN + 1];
|
||||||
|
char tbl_buf[NAME_LEN + 1], tbl_buf1[NAME_LEN + 1];
|
||||||
|
ulint db_buf_len, db_buf1_len;
|
||||||
|
ulint tbl_buf_len, tbl_buf1_len;
|
||||||
|
|
||||||
|
if (!table_name_parse(table->name, db_buf, tbl_buf,
|
||||||
|
db_buf_len, tbl_buf_len)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const table_id_t table_id = table->id;
|
||||||
|
retry_mdl:
|
||||||
|
const bool unaccessible = !table->is_readable() || table->corrupted;
|
||||||
|
table->release();
|
||||||
|
|
||||||
|
if (unaccessible) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
TABLE* mariadb_table = open_purge_table(thd, db_buf, db_buf_len,
|
||||||
|
tbl_buf, tbl_buf_len);
|
||||||
|
|
||||||
|
table = dict_table_open_on_id(table_id, false, DICT_TABLE_OP_NORMAL);
|
||||||
|
|
||||||
|
if (table == NULL) {
|
||||||
|
/* Table is dropped. */
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fil_table_accessible(table)) {
|
||||||
|
release_fail:
|
||||||
|
table->release();
|
||||||
|
fail:
|
||||||
|
if (mariadb_table) {
|
||||||
|
close_thread_tables(thd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!table_name_parse(table->name, db_buf1, tbl_buf1,
|
||||||
|
db_buf1_len, tbl_buf1_len)) {
|
||||||
|
goto release_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mariadb_table) {
|
||||||
|
} else if (!strcmp(db_buf, db_buf1) && !strcmp(tbl_buf, tbl_buf1)) {
|
||||||
|
return mariadb_table;
|
||||||
} else {
|
} else {
|
||||||
if (table->vc_templ->mysql_table_query_id == thd_get_query_id(thd)) {
|
/* Table is renamed. So release MDL for old name and try
|
||||||
|
to acquire the MDL for new table name. */
|
||||||
|
close_thread_tables(thd);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(tbl_buf, tbl_buf1);
|
||||||
|
strcpy(db_buf, db_buf1);
|
||||||
|
tbl_buf_len = tbl_buf1_len;
|
||||||
|
db_buf_len = db_buf1_len;
|
||||||
|
goto retry_mdl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Find or open a table handle for the virtual column template
|
||||||
|
@param[in] thd thread handle
|
||||||
|
@param[in,out] table InnoDB table whose virtual column template
|
||||||
|
is to be updated
|
||||||
|
@return table handle
|
||||||
|
@retval NULL if the table is dropped, unaccessible or corrupted
|
||||||
|
for purge thread */
|
||||||
|
static TABLE* innodb_find_table_for_vc(THD* thd, dict_table_t* table)
|
||||||
|
{
|
||||||
|
if (THDVAR(thd, background_thread)) {
|
||||||
|
/* Purge thread acquires dict_operation_lock while
|
||||||
|
processing undo log record. Release the dict_operation_lock
|
||||||
|
before acquiring MDL on the table. */
|
||||||
|
rw_lock_s_unlock(dict_operation_lock);
|
||||||
|
return innodb_acquire_mdl(thd, table);
|
||||||
|
} else {
|
||||||
|
if (table->vc_templ->mysql_table_query_id
|
||||||
|
== thd_get_query_id(thd)) {
|
||||||
return table->vc_templ->mysql_table;
|
return table->vc_templ->mysql_table;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char dbname[MAX_DATABASE_NAME_LEN + 1];
|
char db_buf[NAME_LEN + 1];
|
||||||
char tbname[MAX_TABLE_NAME_LEN + 1];
|
char tbl_buf[NAME_LEN + 1];
|
||||||
char* name = table->name.m_name;
|
ulint db_buf_len, tbl_buf_len;
|
||||||
uint dbnamelen = (uint) dict_get_db_name_len(name);
|
|
||||||
uint tbnamelen = (uint) strlen(name) - dbnamelen - 1;
|
|
||||||
char t_dbname[MAX_DATABASE_NAME_LEN + 1];
|
|
||||||
char t_tbname[MAX_TABLE_NAME_LEN + 1];
|
|
||||||
|
|
||||||
strncpy(dbname, name, dbnamelen);
|
if (!table_name_parse(table->name, db_buf, tbl_buf,
|
||||||
dbname[dbnamelen] = 0;
|
db_buf_len, tbl_buf_len)) {
|
||||||
strncpy(tbname, name + dbnamelen + 1, tbnamelen);
|
return NULL;
|
||||||
tbname[tbnamelen] =0;
|
|
||||||
|
|
||||||
/* For partition table, remove the partition name and use the
|
|
||||||
"main" table name to build the template */
|
|
||||||
char* is_part = is_partition(tbname);
|
|
||||||
|
|
||||||
if (is_part != NULL) {
|
|
||||||
*is_part = '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dbnamelen = filename_to_tablename(dbname, t_dbname,
|
TABLE* mysql_table = find_fk_open_table(thd, db_buf, db_buf_len,
|
||||||
MAX_DATABASE_NAME_LEN + 1);
|
tbl_buf, tbl_buf_len);
|
||||||
tbnamelen = filename_to_tablename(tbname, t_tbname,
|
|
||||||
MAX_TABLE_NAME_LEN + 1);
|
|
||||||
|
|
||||||
if (bg_thread) {
|
|
||||||
return open_purge_table(thd, t_dbname, dbnamelen,
|
|
||||||
t_tbname, tbnamelen);
|
|
||||||
}
|
|
||||||
|
|
||||||
mysql_table = find_fk_open_table(thd, t_dbname, dbnamelen,
|
|
||||||
t_tbname, tbnamelen);
|
|
||||||
|
|
||||||
table->vc_templ->mysql_table = mysql_table;
|
table->vc_templ->mysql_table = mysql_table;
|
||||||
table->vc_templ->mysql_table_query_id = thd_get_query_id(thd);
|
table->vc_templ->mysql_table_query_id = thd_get_query_id(thd);
|
||||||
@ -20693,7 +20781,7 @@ innobase_init_vc_templ(
|
|||||||
|
|
||||||
table->vc_templ = UT_NEW_NOKEY(dict_vcol_templ_t());
|
table->vc_templ = UT_NEW_NOKEY(dict_vcol_templ_t());
|
||||||
|
|
||||||
TABLE *mysql_table= innobase_find_mysql_table_for_vc(current_thd, table);
|
TABLE *mysql_table= innodb_find_table_for_vc(current_thd, table);
|
||||||
|
|
||||||
ut_ad(mysql_table);
|
ut_ad(mysql_table);
|
||||||
if (!mysql_table) {
|
if (!mysql_table) {
|
||||||
@ -20787,15 +20875,16 @@ innobase_get_field_from_update_vector(
|
|||||||
Allocate a heap and record for calculating virtual fields
|
Allocate a heap and record for calculating virtual fields
|
||||||
Used mainly for virtual fields in indexes
|
Used mainly for virtual fields in indexes
|
||||||
|
|
||||||
@param[in] thd MariaDB THD
|
@param[in] thd MariaDB THD
|
||||||
@param[in] index Index in use
|
@param[in] index Index in use
|
||||||
@param[out] heap Heap that holds temporary row
|
@param[out] heap Heap that holds temporary row
|
||||||
@param[in,out] mysql_table MariaDB table
|
@param[in,out] table MariaDB table
|
||||||
@param[out] rec Pointer to allocated MariaDB record
|
@param[out] record Pointer to allocated MariaDB record
|
||||||
@param[out] storage Internal storage for blobs etc
|
@param[out] storage Internal storage for blobs etc
|
||||||
|
|
||||||
@return FALSE ok
|
@retval false on success
|
||||||
@return TRUE malloc failure
|
@retval true on malloc failure or failed to open the maria table
|
||||||
|
for purge thread.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool innobase_allocate_row_for_vcol(
|
bool innobase_allocate_row_for_vcol(
|
||||||
@ -20809,7 +20898,12 @@ bool innobase_allocate_row_for_vcol(
|
|||||||
TABLE *maria_table;
|
TABLE *maria_table;
|
||||||
String *blob_value_storage;
|
String *blob_value_storage;
|
||||||
if (!*table)
|
if (!*table)
|
||||||
*table= innobase_find_mysql_table_for_vc(thd, index->table);
|
*table= innodb_find_table_for_vc(thd, index->table);
|
||||||
|
|
||||||
|
/* For purge thread, there is a possiblity that table could have
|
||||||
|
dropped, corrupted or unaccessible. */
|
||||||
|
if (!*table)
|
||||||
|
return true;
|
||||||
maria_table= *table;
|
maria_table= *table;
|
||||||
if (!*heap && !(*heap= mem_heap_create(srv_page_size)))
|
if (!*heap && !(*heap= mem_heap_create(srv_page_size)))
|
||||||
{
|
{
|
||||||
|
@ -121,7 +121,15 @@ enum btr_latch_mode {
|
|||||||
/** Attempt to purge a secondary index record
|
/** Attempt to purge a secondary index record
|
||||||
while holding the dict_index_t::lock S-latch. */
|
while holding the dict_index_t::lock S-latch. */
|
||||||
BTR_PURGE_LEAF_ALREADY_S_LATCHED = BTR_PURGE_LEAF
|
BTR_PURGE_LEAF_ALREADY_S_LATCHED = BTR_PURGE_LEAF
|
||||||
| BTR_ALREADY_S_LATCHED
|
| BTR_ALREADY_S_LATCHED,
|
||||||
|
|
||||||
|
/** In the case of BTR_MODIFY_TREE, the caller specifies
|
||||||
|
the intention to delete record only. It is used to optimize
|
||||||
|
block->lock range.*/
|
||||||
|
BTR_LATCH_FOR_DELETE = 65536,
|
||||||
|
|
||||||
|
/** Attempt to purge a secondary index record in the tree. */
|
||||||
|
BTR_PURGE_TREE = BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE
|
||||||
};
|
};
|
||||||
|
|
||||||
/** This flag ORed to btr_latch_mode says that we do the search in query
|
/** This flag ORed to btr_latch_mode says that we do the search in query
|
||||||
@ -137,10 +145,6 @@ the insert buffer to speed up inserts */
|
|||||||
to insert record only. It is used to optimize block->lock range.*/
|
to insert record only. It is used to optimize block->lock range.*/
|
||||||
#define BTR_LATCH_FOR_INSERT 32768U
|
#define BTR_LATCH_FOR_INSERT 32768U
|
||||||
|
|
||||||
/** In the case of BTR_MODIFY_TREE, the caller specifies the intention
|
|
||||||
to delete record only. It is used to optimize block->lock range.*/
|
|
||||||
#define BTR_LATCH_FOR_DELETE 65536U
|
|
||||||
|
|
||||||
/** This flag is for undo insert of rtree. For rtree, we need this flag
|
/** This flag is for undo insert of rtree. For rtree, we need this flag
|
||||||
to find proper rec to undo insert.*/
|
to find proper rec to undo insert.*/
|
||||||
#define BTR_RTREE_UNDO_INS 131072U
|
#define BTR_RTREE_UNDO_INS 131072U
|
||||||
|
@ -301,6 +301,21 @@ btr_pcur_commit_specify_mtr(
|
|||||||
/*========================*/
|
/*========================*/
|
||||||
btr_pcur_t* pcur, /*!< in: persistent cursor */
|
btr_pcur_t* pcur, /*!< in: persistent cursor */
|
||||||
mtr_t* mtr); /*!< in: mtr to commit */
|
mtr_t* mtr); /*!< in: mtr to commit */
|
||||||
|
|
||||||
|
/** Commits the mtr and sets the clustered index pcur and secondary index
|
||||||
|
pcur latch mode to BTR_NO_LATCHES, that is, the cursor becomes detached.
|
||||||
|
Function btr_pcur_store_position should be used for both cursor before
|
||||||
|
calling this, if restoration of cursor is wanted later.
|
||||||
|
@param[in] pcur persistent cursor
|
||||||
|
@param[in] sec_pcur secondary index persistent cursor
|
||||||
|
@param[in] mtr mtr to commit */
|
||||||
|
UNIV_INLINE
|
||||||
|
void
|
||||||
|
btr_pcurs_commit_specify_mtr(
|
||||||
|
btr_pcur_t* pcur,
|
||||||
|
btr_pcur_t* sec_pcur,
|
||||||
|
mtr_t* mtr);
|
||||||
|
|
||||||
/*********************************************************//**
|
/*********************************************************//**
|
||||||
Moves the persistent cursor to the next record in the tree. If no records are
|
Moves the persistent cursor to the next record in the tree. If no records are
|
||||||
left, the cursor stays 'after last in tree'.
|
left, the cursor stays 'after last in tree'.
|
||||||
|
@ -365,6 +365,32 @@ btr_pcur_commit_specify_mtr(
|
|||||||
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
|
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Commits the mtr and sets the clustered index pcur and secondary index
|
||||||
|
pcur latch mode to BTR_NO_LATCHES, that is, the cursor becomes detached.
|
||||||
|
Function btr_pcur_store_position should be used for both cursor before
|
||||||
|
calling this, if restoration of cursor is wanted later.
|
||||||
|
@param[in] pcur persistent cursor
|
||||||
|
@param[in] sec_pcur secondary index persistent cursor
|
||||||
|
@param[in] mtr mtr to commit */
|
||||||
|
UNIV_INLINE
|
||||||
|
void
|
||||||
|
btr_pcurs_commit_specify_mtr(
|
||||||
|
btr_pcur_t* pcur,
|
||||||
|
btr_pcur_t* sec_pcur,
|
||||||
|
mtr_t* mtr)
|
||||||
|
{
|
||||||
|
ut_ad(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||||
|
ut_ad(sec_pcur->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||||
|
|
||||||
|
pcur->latch_mode = BTR_NO_LATCHES;
|
||||||
|
sec_pcur->latch_mode = BTR_NO_LATCHES;
|
||||||
|
|
||||||
|
mtr_commit(mtr);
|
||||||
|
|
||||||
|
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
|
||||||
|
sec_pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************//**
|
/**************************************************************//**
|
||||||
Sets the old_rec_buf field to NULL. */
|
Sets the old_rec_buf field to NULL. */
|
||||||
UNIV_INLINE
|
UNIV_INLINE
|
||||||
|
@ -171,6 +171,9 @@ static inline bool btr_search_own_all(ulint mode);
|
|||||||
@retval true if owns any of them
|
@retval true if owns any of them
|
||||||
@retval false if owns no search latch */
|
@retval false if owns no search latch */
|
||||||
static inline bool btr_search_own_any(ulint mode);
|
static inline bool btr_search_own_any(ulint mode);
|
||||||
|
|
||||||
|
/** @return whether this thread holds any of the search latches */
|
||||||
|
static inline bool btr_search_own_any();
|
||||||
#endif /* UNIV_DEBUG */
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
||||||
/** Unlock all search latches from shared mode. */
|
/** Unlock all search latches from shared mode. */
|
||||||
|
@ -144,6 +144,18 @@ static inline bool btr_search_own_any(ulint mode)
|
|||||||
}
|
}
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return whether this thread holds any of the search latches */
|
||||||
|
static inline bool btr_search_own_any()
|
||||||
|
{
|
||||||
|
for (ulint i = btr_ahi_parts; i--; ) {
|
||||||
|
if (rw_lock_own_flagged(btr_search_latches[i],
|
||||||
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#endif /* UNIV_DEBUG */
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
||||||
/** Get the adaptive hash search index latch for a b-tree.
|
/** Get the adaptive hash search index latch for a b-tree.
|
||||||
|
@ -1401,23 +1401,13 @@ dict_table_is_file_per_table(
|
|||||||
&& table->space != fil_system.temp_space;
|
&& table->space != fil_system.temp_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get reference count.
|
|
||||||
@return current value of n_ref_count */
|
|
||||||
inline
|
|
||||||
ulint
|
|
||||||
dict_table_t::get_ref_count() const
|
|
||||||
{
|
|
||||||
ut_ad(mutex_own(&dict_sys->mutex));
|
|
||||||
return(n_ref_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Acquire the table handle. */
|
/** Acquire the table handle. */
|
||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
dict_table_t::acquire()
|
dict_table_t::acquire()
|
||||||
{
|
{
|
||||||
ut_ad(mutex_own(&dict_sys->mutex));
|
ut_ad(mutex_own(&dict_sys->mutex));
|
||||||
++n_ref_count;
|
my_atomic_add32_explicit(&n_ref_count, 1, MY_MEMORY_ORDER_RELAXED);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Release the table handle.
|
/** Release the table handle.
|
||||||
@ -1426,9 +1416,10 @@ inline
|
|||||||
bool
|
bool
|
||||||
dict_table_t::release()
|
dict_table_t::release()
|
||||||
{
|
{
|
||||||
ut_ad(mutex_own(&dict_sys->mutex));
|
int32 n = my_atomic_add32_explicit(
|
||||||
ut_ad(n_ref_count > 0);
|
&n_ref_count, -1, MY_MEMORY_ORDER_RELAXED);
|
||||||
return !--n_ref_count;
|
ut_ad(n > 0);
|
||||||
|
return n == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Encode the number of columns and number of virtual columns in a
|
/** Encode the number of columns and number of virtual columns in a
|
||||||
|
@ -1481,7 +1481,11 @@ struct dict_table_t {
|
|||||||
|
|
||||||
/** Get reference count.
|
/** Get reference count.
|
||||||
@return current value of n_ref_count */
|
@return current value of n_ref_count */
|
||||||
inline ulint get_ref_count() const;
|
inline int32 get_ref_count()
|
||||||
|
{
|
||||||
|
return my_atomic_load32_explicit(&n_ref_count,
|
||||||
|
MY_MEMORY_ORDER_RELAXED);
|
||||||
|
}
|
||||||
|
|
||||||
/** Acquire the table handle. */
|
/** Acquire the table handle. */
|
||||||
inline void acquire();
|
inline void acquire();
|
||||||
@ -1928,13 +1932,11 @@ struct dict_table_t {
|
|||||||
It is protected by lock_sys.mutex. */
|
It is protected by lock_sys.mutex. */
|
||||||
ulint n_rec_locks;
|
ulint n_rec_locks;
|
||||||
|
|
||||||
#ifndef DBUG_ASSERT_EXISTS
|
|
||||||
private:
|
private:
|
||||||
#endif
|
|
||||||
/** Count of how many handles are opened to this table. Dropping of the
|
/** Count of how many handles are opened to this table. Dropping of the
|
||||||
table is NOT allowed until this count gets to zero. MySQL does NOT
|
table is NOT allowed until this count gets to zero. MySQL does NOT
|
||||||
itself check the number of open handles at DROP. */
|
itself check the number of open handles at DROP. */
|
||||||
ulint n_ref_count;
|
int32 n_ref_count;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** List of locks on the table. Protected by lock_sys.mutex. */
|
/** List of locks on the table. Protected by lock_sys.mutex. */
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2018, MariaDB Corporation.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -137,11 +138,8 @@ hash_assert_can_search(
|
|||||||
if (table->type == HASH_TABLE_SYNC_MUTEX) {
|
if (table->type == HASH_TABLE_SYNC_MUTEX) {
|
||||||
ut_ad(mutex_own(hash_get_mutex(table, fold)));
|
ut_ad(mutex_own(hash_get_mutex(table, fold)));
|
||||||
} else if (table->type == HASH_TABLE_SYNC_RW_LOCK) {
|
} else if (table->type == HASH_TABLE_SYNC_RW_LOCK) {
|
||||||
# ifdef UNIV_DEBUG
|
ut_ad(rw_lock_own_flagged(hash_get_lock(table, fold),
|
||||||
rw_lock_t* lock = hash_get_lock(table, fold);
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
ut_ad(rw_lock_own(lock, RW_LOCK_X)
|
|
||||||
|| rw_lock_own(lock, RW_LOCK_S));
|
|
||||||
# endif
|
|
||||||
} else {
|
} else {
|
||||||
ut_ad(table->type == HASH_TABLE_SYNC_NONE);
|
ut_ad(table->type == HASH_TABLE_SYNC_NONE);
|
||||||
}
|
}
|
||||||
|
@ -789,19 +789,21 @@ const lock_t*
|
|||||||
lock_trx_has_sys_table_locks(
|
lock_trx_has_sys_table_locks(
|
||||||
/*=========================*/
|
/*=========================*/
|
||||||
const trx_t* trx) /*!< in: transaction to check */
|
const trx_t* trx) /*!< in: transaction to check */
|
||||||
MY_ATTRIBUTE((warn_unused_result));
|
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||||
|
|
||||||
/*******************************************************************//**
|
/** Check if the transaction holds an explicit exclusive lock on a record.
|
||||||
Check if the transaction holds an exclusive lock on a record.
|
@param[in] trx transaction
|
||||||
@return whether the locks are held */
|
@param[in] table table
|
||||||
|
@param[in] block leaf page
|
||||||
|
@param[in] heap_no heap number identifying the record
|
||||||
|
@return whether an explicit X-lock is held */
|
||||||
bool
|
bool
|
||||||
lock_trx_has_rec_x_lock(
|
lock_trx_has_expl_x_lock(
|
||||||
/*====================*/
|
|
||||||
const trx_t* trx, /*!< in: transaction to check */
|
const trx_t* trx, /*!< in: transaction to check */
|
||||||
const dict_table_t* table, /*!< in: table to check */
|
const dict_table_t* table, /*!< in: table to check */
|
||||||
const buf_block_t* block, /*!< in: buffer block of the record */
|
const buf_block_t* block, /*!< in: buffer block of the record */
|
||||||
ulint heap_no)/*!< in: record heap number */
|
ulint heap_no)/*!< in: record heap number */
|
||||||
MY_ATTRIBUTE((warn_unused_result));
|
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||||
#endif /* UNIV_DEBUG */
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,6 +36,7 @@ Created 3/14/1997 Heikki Tuuri
|
|||||||
#include "que0types.h"
|
#include "que0types.h"
|
||||||
#include "row0types.h"
|
#include "row0types.h"
|
||||||
#include "ut0vec.h"
|
#include "ut0vec.h"
|
||||||
|
#include "row0mysql.h"
|
||||||
|
|
||||||
/** Create a purge node to a query graph.
|
/** Create a purge node to a query graph.
|
||||||
@param[in] parent parent node, i.e., a thr node
|
@param[in] parent parent node, i.e., a thr node
|
||||||
@ -47,8 +48,7 @@ row_purge_node_create(
|
|||||||
mem_heap_t* heap)
|
mem_heap_t* heap)
|
||||||
MY_ATTRIBUTE((warn_unused_result));
|
MY_ATTRIBUTE((warn_unused_result));
|
||||||
|
|
||||||
/***********************************************************//**
|
/** Determines if it is possible to remove a secondary index entry.
|
||||||
Determines if it is possible to remove a secondary index entry.
|
|
||||||
Removal is possible if the secondary index entry does not refer to any
|
Removal is possible if the secondary index entry does not refer to any
|
||||||
not delete marked version of a clustered index record where DB_TRX_ID
|
not delete marked version of a clustered index record where DB_TRX_ID
|
||||||
is newer than the purge view.
|
is newer than the purge view.
|
||||||
@ -61,14 +61,27 @@ inserts a record that the secondary index entry would refer to.
|
|||||||
However, in that case, the user transaction would also re-insert the
|
However, in that case, the user transaction would also re-insert the
|
||||||
secondary index entry after purge has removed it and released the leaf
|
secondary index entry after purge has removed it and released the leaf
|
||||||
page latch.
|
page latch.
|
||||||
|
@param[in,out] node row purge node
|
||||||
|
@param[in] index secondary index
|
||||||
|
@param[in] entry secondary index entry
|
||||||
|
@param[in,out] sec_pcur secondary index cursor or NULL
|
||||||
|
if it is called for purge buffering
|
||||||
|
operation.
|
||||||
|
@param[in,out] sec_mtr mini-transaction which holds
|
||||||
|
secondary index entry or NULL if it is
|
||||||
|
called for purge buffering operation.
|
||||||
|
@param[in] is_tree true=pessimistic purge,
|
||||||
|
false=optimistic (leaf-page only)
|
||||||
@return true if the secondary index record can be purged */
|
@return true if the secondary index record can be purged */
|
||||||
bool
|
bool
|
||||||
row_purge_poss_sec(
|
row_purge_poss_sec(
|
||||||
/*===============*/
|
purge_node_t* node,
|
||||||
purge_node_t* node, /*!< in/out: row purge node */
|
dict_index_t* index,
|
||||||
dict_index_t* index, /*!< in: secondary index */
|
const dtuple_t* entry,
|
||||||
const dtuple_t* entry) /*!< in: secondary index entry */
|
btr_pcur_t* sec_pcur=NULL,
|
||||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
mtr_t* sec_mtr=NULL,
|
||||||
|
bool is_tree=false);
|
||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
Does the purge operation for a single undo log record. This is a high-level
|
Does the purge operation for a single undo log record. This is a high-level
|
||||||
function used in an SQL execution graph.
|
function used in an SQL execution graph.
|
||||||
@ -117,6 +130,10 @@ struct purge_node_t{
|
|||||||
ibool done; /* Debug flag */
|
ibool done; /* Debug flag */
|
||||||
trx_id_t trx_id; /*!< trx id for this purging record */
|
trx_id_t trx_id; /*!< trx id for this purging record */
|
||||||
|
|
||||||
|
/** Virtual column information about opening of MariaDB table.
|
||||||
|
It resets after processing each undo log record. */
|
||||||
|
purge_vcol_info_t vcol_info;
|
||||||
|
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
/***********************************************************//**
|
/***********************************************************//**
|
||||||
Validate the persisent cursor. The purge node has two references
|
Validate the persisent cursor. The purge node has two references
|
||||||
@ -125,8 +142,13 @@ struct purge_node_t{
|
|||||||
each other if the found_clust flag is set.
|
each other if the found_clust flag is set.
|
||||||
@return true if the persistent cursor is consistent with
|
@return true if the persistent cursor is consistent with
|
||||||
the ref member.*/
|
the ref member.*/
|
||||||
bool validate_pcur();
|
bool validate_pcur();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** Whether purge failed to open the maria table for virtual column
|
||||||
|
computation.
|
||||||
|
@return true if the table failed to open. */
|
||||||
|
bool vcol_op_failed() const { return !vcol_info.validate(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
|
Copyright (c) 2018, MariaDB Corporation.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -52,4 +53,93 @@ struct row_log_t;
|
|||||||
/* MySQL data types */
|
/* MySQL data types */
|
||||||
struct TABLE;
|
struct TABLE;
|
||||||
|
|
||||||
|
/** Purge virtual column node information. */
|
||||||
|
struct purge_vcol_info_t
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/** Is there a possible need to evaluate virtual columns? */
|
||||||
|
bool requested;
|
||||||
|
/** Do we have to evaluate virtual columns (using mariadb_table)? */
|
||||||
|
bool used;
|
||||||
|
|
||||||
|
/** True if it is used for the first time. */
|
||||||
|
bool first_use;
|
||||||
|
|
||||||
|
/** MariaDB table opened for virtual column computation. */
|
||||||
|
TABLE* mariadb_table;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Reset the state. */
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
requested = false;
|
||||||
|
used = false;
|
||||||
|
first_use = false;
|
||||||
|
mariadb_table = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Validate the virtual column information.
|
||||||
|
@return true if the mariadb table opened successfully
|
||||||
|
or doesn't try to calculate virtual column. */
|
||||||
|
bool validate() const { return !used || mariadb_table; }
|
||||||
|
|
||||||
|
/** @return the table handle for evaluating virtual columns */
|
||||||
|
TABLE* table() const { return mariadb_table; }
|
||||||
|
|
||||||
|
/** Set the table handle for evaluating virtual columns.
|
||||||
|
@param[in] table table handle */
|
||||||
|
void set_table(TABLE* table)
|
||||||
|
{
|
||||||
|
ut_ad(!table || is_first_fetch());
|
||||||
|
mariadb_table = table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Note that virtual column information may be needed. */
|
||||||
|
void set_requested()
|
||||||
|
{
|
||||||
|
ut_ad(!used);
|
||||||
|
ut_ad(!first_use);
|
||||||
|
ut_ad(!mariadb_table);
|
||||||
|
requested = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return whether the virtual column information may be needed */
|
||||||
|
bool is_requested() const { return requested; }
|
||||||
|
|
||||||
|
/** Note that the virtual column information is needed. */
|
||||||
|
void set_used()
|
||||||
|
{
|
||||||
|
ut_ad(requested);
|
||||||
|
|
||||||
|
if (first_use) {
|
||||||
|
first_use = false;
|
||||||
|
ut_ad(used);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!used) {
|
||||||
|
first_use = used = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return whether the virtual column information is needed */
|
||||||
|
bool is_used() const
|
||||||
|
{
|
||||||
|
ut_ad(!first_use || used);
|
||||||
|
ut_ad(!used || requested);
|
||||||
|
ut_ad(used || !mariadb_table);
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check whether it fetches mariadb table for the first time.
|
||||||
|
@return true if first time tries to open mariadb table. */
|
||||||
|
bool is_first_fetch() const
|
||||||
|
{
|
||||||
|
ut_ad(!first_use || used);
|
||||||
|
ut_ad(!used || requested);
|
||||||
|
ut_ad(used || !mariadb_table);
|
||||||
|
return first_use;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,6 +35,7 @@ Created 2/6/1997 Heikki Tuuri
|
|||||||
#include "rem0types.h"
|
#include "rem0types.h"
|
||||||
#include "mtr0mtr.h"
|
#include "mtr0mtr.h"
|
||||||
#include "dict0mem.h"
|
#include "dict0mem.h"
|
||||||
|
#include "row0types.h"
|
||||||
|
|
||||||
// Forward declaration
|
// Forward declaration
|
||||||
class ReadView;
|
class ReadView;
|
||||||
@ -54,27 +55,34 @@ row_vers_impl_x_locked(
|
|||||||
dict_index_t* index,
|
dict_index_t* index,
|
||||||
const ulint* offsets);
|
const ulint* offsets);
|
||||||
|
|
||||||
/*****************************************************************//**
|
/** Finds out if a version of the record, where the version >= the current
|
||||||
Finds out if a version of the record, where the version >= the current
|
|
||||||
purge view, should have ientry as its secondary index entry. We check
|
purge view, should have ientry as its secondary index entry. We check
|
||||||
if there is any not delete marked version of the record where the trx
|
if there is any not delete marked version of the record where the trx
|
||||||
id >= purge view, and the secondary index entry == ientry; exactly in
|
id >= purge view, and the secondary index entry == ientry; exactly in
|
||||||
this case we return TRUE.
|
this case we return TRUE.
|
||||||
|
@param[in] also_curr TRUE if also rec is included in the versions
|
||||||
|
to search; otherwise only versions prior
|
||||||
|
to it are searched
|
||||||
|
@param[in] rec record in the clustered index; the caller
|
||||||
|
must have a latch on the page
|
||||||
|
@param[in] mtr mtr holding the latch on rec; it will
|
||||||
|
also hold the latch on purge_view
|
||||||
|
@param[in] index secondary index
|
||||||
|
@param[in] ientry secondary index entry
|
||||||
|
@param[in] roll_ptr roll_ptr for the purge record
|
||||||
|
@param[in] trx_id transaction ID on the purging record
|
||||||
|
@param[in,out] vcol_info virtual column information for purge thread.
|
||||||
@return TRUE if earlier version should have */
|
@return TRUE if earlier version should have */
|
||||||
ibool
|
bool
|
||||||
row_vers_old_has_index_entry(
|
row_vers_old_has_index_entry(
|
||||||
/*=========================*/
|
bool also_curr,
|
||||||
ibool also_curr,/*!< in: TRUE if also rec is included in the
|
const rec_t* rec,
|
||||||
versions to search; otherwise only versions
|
mtr_t* mtr,
|
||||||
prior to it are searched */
|
dict_index_t* index,
|
||||||
const rec_t* rec, /*!< in: record in the clustered index; the
|
const dtuple_t* ientry,
|
||||||
caller must have a latch on the page */
|
roll_ptr_t roll_ptr,
|
||||||
mtr_t* mtr, /*!< in: mtr holding the latch on rec; it will
|
trx_id_t trx_id,
|
||||||
also hold the latch on purge_view */
|
purge_vcol_info_t* vcol_info=NULL);
|
||||||
dict_index_t* index, /*!< in: the secondary index */
|
|
||||||
const dtuple_t* ientry, /*!< in: the secondary index entry */
|
|
||||||
roll_ptr_t roll_ptr,/*!< in: roll_ptr for the purge record */
|
|
||||||
trx_id_t trx_id);/*!< in: transaction ID on the purging record */
|
|
||||||
|
|
||||||
/*****************************************************************//**
|
/*****************************************************************//**
|
||||||
Constructs the version of a clustered index record which a consistent
|
Constructs the version of a clustered index record which a consistent
|
||||||
|
@ -279,8 +279,7 @@ rw_lock_s_lock_func(
|
|||||||
the threads which have s-locked a latch. This would use some CPU
|
the threads which have s-locked a latch. This would use some CPU
|
||||||
time. */
|
time. */
|
||||||
|
|
||||||
ut_ad(!rw_lock_own(lock, RW_LOCK_S)); /* see NOTE above */
|
ut_ad(!rw_lock_own_flagged(lock, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
ut_ad(!rw_lock_own(lock, RW_LOCK_X));
|
|
||||||
|
|
||||||
if (!rw_lock_s_lock_low(lock, pass, file_name, line)) {
|
if (!rw_lock_s_lock_low(lock, pass, file_name, line)) {
|
||||||
|
|
||||||
|
@ -979,8 +979,7 @@ struct latch_t {
|
|||||||
UNIV_NOTHROW
|
UNIV_NOTHROW
|
||||||
:
|
:
|
||||||
m_id(id),
|
m_id(id),
|
||||||
m_rw_lock(),
|
m_rw_lock() {}
|
||||||
m_temp_fsp() { }
|
|
||||||
|
|
||||||
/** Destructor */
|
/** Destructor */
|
||||||
virtual ~latch_t() UNIV_NOTHROW { }
|
virtual ~latch_t() UNIV_NOTHROW { }
|
||||||
@ -1014,24 +1013,6 @@ struct latch_t {
|
|||||||
return(sync_latch_get_level(m_id));
|
return(sync_latch_get_level(m_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return true if the latch is for a temporary file space*/
|
|
||||||
bool is_temp_fsp() const
|
|
||||||
UNIV_NOTHROW
|
|
||||||
{
|
|
||||||
return(m_temp_fsp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the temporary tablespace flag. (For internal temporary
|
|
||||||
tables, MySQL 5.7 does not always acquire the index->lock. We
|
|
||||||
need to figure out the context and add some special rules
|
|
||||||
during the checks.) */
|
|
||||||
void set_temp_fsp()
|
|
||||||
UNIV_NOTHROW
|
|
||||||
{
|
|
||||||
ut_ad(get_id() == LATCH_ID_FIL_SPACE);
|
|
||||||
m_temp_fsp = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return the latch name, m_id must be set */
|
/** @return the latch name, m_id must be set */
|
||||||
const char* get_name() const
|
const char* get_name() const
|
||||||
UNIV_NOTHROW
|
UNIV_NOTHROW
|
||||||
@ -1047,9 +1028,6 @@ struct latch_t {
|
|||||||
/** true if it is a rw-lock. In debug mode, rw_lock_t derives from
|
/** true if it is a rw-lock. In debug mode, rw_lock_t derives from
|
||||||
this class and sets this variable. */
|
this class and sets this variable. */
|
||||||
bool m_rw_lock;
|
bool m_rw_lock;
|
||||||
|
|
||||||
/** true if it is an temporary space latch */
|
|
||||||
bool m_temp_fsp;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Subclass this to iterate over a thread's acquired latch levels. */
|
/** Subclass this to iterate over a thread's acquired latch levels. */
|
||||||
|
@ -616,7 +616,7 @@ public:
|
|||||||
@retval pointer to trx
|
@retval pointer to trx
|
||||||
*/
|
*/
|
||||||
|
|
||||||
trx_t *find(trx_t *caller_trx, trx_id_t trx_id, bool do_ref_count= false)
|
trx_t *find(trx_t *caller_trx, trx_id_t trx_id, bool do_ref_count)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
In MariaDB 10.3, purge will reset DB_TRX_ID to 0
|
In MariaDB 10.3, purge will reset DB_TRX_ID to 0
|
||||||
@ -624,9 +624,10 @@ public:
|
|||||||
always have a nonzero trx_t::id; there the value 0 is
|
always have a nonzero trx_t::id; there the value 0 is
|
||||||
reserved for transactions that did not write or lock
|
reserved for transactions that did not write or lock
|
||||||
anything yet.
|
anything yet.
|
||||||
|
|
||||||
|
The caller should already have handled trx_id==0 specially.
|
||||||
*/
|
*/
|
||||||
if (!trx_id)
|
ut_ad(trx_id);
|
||||||
return NULL;
|
|
||||||
if (caller_trx && caller_trx->id == trx_id)
|
if (caller_trx && caller_trx->id == trx_id)
|
||||||
{
|
{
|
||||||
if (do_ref_count)
|
if (do_ref_count)
|
||||||
@ -1044,13 +1045,13 @@ public:
|
|||||||
|
|
||||||
bool is_registered(trx_t *caller_trx, trx_id_t id)
|
bool is_registered(trx_t *caller_trx, trx_id_t id)
|
||||||
{
|
{
|
||||||
return rw_trx_hash.find(caller_trx, id);
|
return id && find(caller_trx, id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
trx_t *find(trx_t *caller_trx, trx_id_t id)
|
trx_t *find(trx_t *caller_trx, trx_id_t id, bool do_ref_count= true)
|
||||||
{
|
{
|
||||||
return rw_trx_hash.find(caller_trx, id, true);
|
return rw_trx_hash.find(caller_trx, id, do_ref_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1433,7 +1433,7 @@ lock_rec_create_low(
|
|||||||
lock_rec_bitmap_reset(lock);
|
lock_rec_bitmap_reset(lock);
|
||||||
lock_rec_set_nth_bit(lock, heap_no);
|
lock_rec_set_nth_bit(lock, heap_no);
|
||||||
index->table->n_rec_locks++;
|
index->table->n_rec_locks++;
|
||||||
ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted);
|
ut_ad(index->table->get_ref_count() > 0 || !index->table->can_be_evicted);
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
if (c_lock && wsrep_on_trx(trx)
|
if (c_lock && wsrep_on_trx(trx)
|
||||||
@ -3531,7 +3531,7 @@ lock_table_create(
|
|||||||
|
|
||||||
lock->un_member.tab_lock.table = table;
|
lock->un_member.tab_lock.table = table;
|
||||||
|
|
||||||
ut_ad(table->n_ref_count > 0 || !table->can_be_evicted);
|
ut_ad(table->get_ref_count() > 0 || !table->can_be_evicted);
|
||||||
|
|
||||||
UT_LIST_ADD_LAST(trx->lock.trx_locks, lock);
|
UT_LIST_ADD_LAST(trx->lock.trx_locks, lock);
|
||||||
|
|
||||||
@ -4937,8 +4937,12 @@ lock_rec_queue_validate(
|
|||||||
/* Unlike the non-debug code, this invariant can only succeed
|
/* Unlike the non-debug code, this invariant can only succeed
|
||||||
if the check and assertion are covered by the lock mutex. */
|
if the check and assertion are covered by the lock mutex. */
|
||||||
|
|
||||||
const trx_t *impl_trx = trx_sys.rw_trx_hash.find(current_trx(),
|
const trx_id_t impl_trx_id = lock_clust_rec_some_has_impl(
|
||||||
lock_clust_rec_some_has_impl(rec, index, offsets));
|
rec, index, offsets);
|
||||||
|
|
||||||
|
const trx_t *impl_trx = impl_trx_id
|
||||||
|
? trx_sys.find(current_trx(), impl_trx_id, false)
|
||||||
|
: 0;
|
||||||
|
|
||||||
ut_ad(lock_mutex_own());
|
ut_ad(lock_mutex_own());
|
||||||
/* impl_trx cannot be committed until lock_mutex_exit()
|
/* impl_trx cannot be committed until lock_mutex_exit()
|
||||||
@ -5547,18 +5551,31 @@ static void lock_rec_other_trx_holds_expl(trx_t *caller_trx, trx_t *trx,
|
|||||||
#endif /* UNIV_DEBUG */
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************//**
|
/** If an implicit x-lock exists on a record, convert it to an explicit one.
|
||||||
If a transaction has an implicit x-lock on a record, but no explicit x-lock
|
|
||||||
set on the record, sets one for it. */
|
Often, this is called by a transaction that is about to enter a lock wait
|
||||||
|
due to the lock conflict. Two explicit locks would be created: first the
|
||||||
|
exclusive lock on behalf of the lock-holder transaction in this function,
|
||||||
|
and then a wait request on behalf of caller_trx, in the calling function.
|
||||||
|
|
||||||
|
This may also be called by the same transaction that is already holding
|
||||||
|
an implicit exclusive lock on the record. In this case, no explicit lock
|
||||||
|
should be created.
|
||||||
|
|
||||||
|
@param[in,out] caller_trx current transaction
|
||||||
|
@param[in] block index tree leaf page
|
||||||
|
@param[in] rec record on the leaf page
|
||||||
|
@param[in] index the index of the record
|
||||||
|
@param[in] offsets rec_get_offsets(rec,index)
|
||||||
|
@return whether caller_trx already holds an exclusive lock on rec */
|
||||||
static
|
static
|
||||||
void
|
bool
|
||||||
lock_rec_convert_impl_to_expl(
|
lock_rec_convert_impl_to_expl(
|
||||||
/*==========================*/
|
trx_t* caller_trx,
|
||||||
trx_t* caller_trx,/*!<in/out: trx of current thread */
|
const buf_block_t* block,
|
||||||
const buf_block_t* block, /*!< in: buffer block of rec */
|
const rec_t* rec,
|
||||||
const rec_t* rec, /*!< in: user record on page */
|
dict_index_t* index,
|
||||||
dict_index_t* index, /*!< in: index of record */
|
const ulint* offsets)
|
||||||
const ulint* offsets)/*!< in: rec_get_offsets(rec, index) */
|
|
||||||
{
|
{
|
||||||
trx_t* trx;
|
trx_t* trx;
|
||||||
|
|
||||||
@ -5574,12 +5591,23 @@ lock_rec_convert_impl_to_expl(
|
|||||||
|
|
||||||
trx_id = lock_clust_rec_some_has_impl(rec, index, offsets);
|
trx_id = lock_clust_rec_some_has_impl(rec, index, offsets);
|
||||||
|
|
||||||
|
if (trx_id == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (UNIV_UNLIKELY(trx_id == caller_trx->id)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
trx = trx_sys.find(caller_trx, trx_id);
|
trx = trx_sys.find(caller_trx, trx_id);
|
||||||
} else {
|
} else {
|
||||||
ut_ad(!dict_index_is_online_ddl(index));
|
ut_ad(!dict_index_is_online_ddl(index));
|
||||||
|
|
||||||
trx = lock_sec_rec_some_has_impl(caller_trx, rec, index,
|
trx = lock_sec_rec_some_has_impl(caller_trx, rec, index,
|
||||||
offsets);
|
offsets);
|
||||||
|
if (trx == caller_trx) {
|
||||||
|
trx->release_reference();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
ut_d(lock_rec_other_trx_holds_expl(caller_trx, trx, rec,
|
ut_d(lock_rec_other_trx_holds_expl(caller_trx, trx, rec,
|
||||||
block));
|
block));
|
||||||
@ -5597,6 +5625,8 @@ lock_rec_convert_impl_to_expl(
|
|||||||
lock_rec_convert_impl_to_expl_for_trx(
|
lock_rec_convert_impl_to_expl_for_trx(
|
||||||
block, rec, index, trx, heap_no);
|
block, rec, index, trx, heap_no);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
@ -5641,8 +5671,11 @@ lock_clust_rec_modify_check_and_lock(
|
|||||||
/* If a transaction has no explicit x-lock set on the record, set one
|
/* If a transaction has no explicit x-lock set on the record, set one
|
||||||
for it */
|
for it */
|
||||||
|
|
||||||
lock_rec_convert_impl_to_expl(thr_get_trx(thr), block, rec, index,
|
if (lock_rec_convert_impl_to_expl(thr_get_trx(thr), block, rec, index,
|
||||||
offsets);
|
offsets)) {
|
||||||
|
/* We already hold an implicit exclusive lock. */
|
||||||
|
return DB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP,
|
err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP,
|
||||||
block, heap_no, index, thr);
|
block, heap_no, index, thr);
|
||||||
@ -5786,10 +5819,11 @@ lock_sec_rec_read_check_and_lock(
|
|||||||
database recovery is running. */
|
database recovery is running. */
|
||||||
|
|
||||||
if (!page_rec_is_supremum(rec)
|
if (!page_rec_is_supremum(rec)
|
||||||
&& page_get_max_trx_id(block->frame) >= trx_sys.get_min_trx_id()) {
|
&& page_get_max_trx_id(block->frame) >= trx_sys.get_min_trx_id()
|
||||||
|
&& lock_rec_convert_impl_to_expl(thr_get_trx(thr), block, rec,
|
||||||
lock_rec_convert_impl_to_expl(thr_get_trx(thr), block, rec,
|
index, offsets)) {
|
||||||
index, offsets);
|
/* We already hold an implicit exclusive lock. */
|
||||||
|
return DB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = lock_rec_lock(FALSE, ulint(mode) | gap_mode,
|
err = lock_rec_lock(FALSE, ulint(mode) | gap_mode,
|
||||||
@ -5850,10 +5884,11 @@ lock_clust_rec_read_check_and_lock(
|
|||||||
|
|
||||||
heap_no = page_rec_get_heap_no(rec);
|
heap_no = page_rec_get_heap_no(rec);
|
||||||
|
|
||||||
if (heap_no != PAGE_HEAP_NO_SUPREMUM) {
|
if (heap_no != PAGE_HEAP_NO_SUPREMUM
|
||||||
|
&& lock_rec_convert_impl_to_expl(thr_get_trx(thr), block, rec,
|
||||||
lock_rec_convert_impl_to_expl(thr_get_trx(thr), block, rec,
|
index, offsets)) {
|
||||||
index, offsets);
|
/* We already hold an implicit exclusive lock. */
|
||||||
|
return DB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = lock_rec_lock(FALSE, ulint(mode) | gap_mode,
|
err = lock_rec_lock(FALSE, ulint(mode) | gap_mode,
|
||||||
@ -6560,12 +6595,14 @@ lock_trx_has_sys_table_locks(
|
|||||||
return(strongest_lock);
|
return(strongest_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************//**
|
/** Check if the transaction holds an explicit exclusive lock on a record.
|
||||||
Check if the transaction holds an exclusive lock on a record.
|
@param[in] trx transaction
|
||||||
@return whether the locks are held */
|
@param[in] table table
|
||||||
|
@param[in] block leaf page
|
||||||
|
@param[in] heap_no heap number identifying the record
|
||||||
|
@return whether an explicit X-lock is held */
|
||||||
bool
|
bool
|
||||||
lock_trx_has_rec_x_lock(
|
lock_trx_has_expl_x_lock(
|
||||||
/*====================*/
|
|
||||||
const trx_t* trx, /*!< in: transaction to check */
|
const trx_t* trx, /*!< in: transaction to check */
|
||||||
const dict_table_t* table, /*!< in: table to check */
|
const dict_table_t* table, /*!< in: table to check */
|
||||||
const buf_block_t* block, /*!< in: buffer block of the record */
|
const buf_block_t* block, /*!< in: buffer block of the record */
|
||||||
@ -6574,11 +6611,9 @@ lock_trx_has_rec_x_lock(
|
|||||||
ut_ad(heap_no > PAGE_HEAP_NO_SUPREMUM);
|
ut_ad(heap_no > PAGE_HEAP_NO_SUPREMUM);
|
||||||
|
|
||||||
lock_mutex_enter();
|
lock_mutex_enter();
|
||||||
ut_a(lock_table_has(trx, table, LOCK_IX)
|
ut_ad(lock_table_has(trx, table, LOCK_IX));
|
||||||
|| table->is_temporary());
|
ut_ad(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, block, heap_no,
|
||||||
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
|
trx));
|
||||||
block, heap_no, trx)
|
|
||||||
|| table->is_temporary());
|
|
||||||
lock_mutex_exit();
|
lock_mutex_exit();
|
||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
|
@ -4062,6 +4062,32 @@ next_file:
|
|||||||
return(status);
|
return(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Check that IO of specific size is possible for the file
|
||||||
|
opened with FILE_FLAG_NO_BUFFERING.
|
||||||
|
|
||||||
|
The requirement is that IO is multiple of the disk sector size.
|
||||||
|
|
||||||
|
@param[in] file file handle
|
||||||
|
@param[in] io_size expected io size
|
||||||
|
@return true - unbuffered io of requested size is possible, false otherwise.
|
||||||
|
|
||||||
|
@note: this function only works correctly with Windows 8 or later,
|
||||||
|
(GetFileInformationByHandleEx with FileStorageInfo is only supported there).
|
||||||
|
It will return true on earlier Windows version.
|
||||||
|
*/
|
||||||
|
static bool unbuffered_io_possible(HANDLE file, size_t io_size)
|
||||||
|
{
|
||||||
|
FILE_STORAGE_INFO info;
|
||||||
|
if (GetFileInformationByHandleEx(
|
||||||
|
file, FileStorageInfo, &info, sizeof(info))) {
|
||||||
|
ULONG sector_size = info.LogicalBytesPerSector;
|
||||||
|
if (sector_size)
|
||||||
|
return io_size % sector_size == 0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** NOTE! Use the corresponding macro os_file_create(), not directly
|
/** NOTE! Use the corresponding macro os_file_create(), not directly
|
||||||
this function!
|
this function!
|
||||||
Opens an existing file or creates a new.
|
Opens an existing file or creates a new.
|
||||||
@ -4237,46 +4263,58 @@ os_file_create_func(
|
|||||||
access |= GENERIC_WRITE;
|
access |= GENERIC_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
for (;;) {
|
||||||
|
const char *operation;
|
||||||
|
|
||||||
/* Use default security attributes and no template file. */
|
/* Use default security attributes and no template file. */
|
||||||
file = CreateFile(
|
file = CreateFile(
|
||||||
(LPCTSTR) name, access, share_mode, NULL,
|
name, access, share_mode, NULL,
|
||||||
create_flag, attributes, NULL);
|
create_flag, attributes, NULL);
|
||||||
|
|
||||||
if (file == INVALID_HANDLE_VALUE) {
|
/* If FILE_FLAG_NO_BUFFERING was set, check if this can work at all,
|
||||||
const char* operation;
|
for expected IO sizes. Reopen without the unbuffered flag, if it is won't work*/
|
||||||
|
if ((file != INVALID_HANDLE_VALUE)
|
||||||
operation = (create_mode == OS_FILE_CREATE
|
&& (attributes & FILE_FLAG_NO_BUFFERING)
|
||||||
&& !read_only)
|
&& (type == OS_LOG_FILE)
|
||||||
? "create" : "open";
|
&& !unbuffered_io_possible(file, OS_FILE_LOG_BLOCK_SIZE)) {
|
||||||
|
ut_a(CloseHandle(file));
|
||||||
*success = false;
|
attributes &= ~FILE_FLAG_NO_BUFFERING;
|
||||||
|
create_flag = OPEN_ALWAYS;
|
||||||
if (on_error_no_exit) {
|
continue;
|
||||||
retry = os_file_handle_error_no_exit(
|
|
||||||
name, operation, on_error_silent);
|
|
||||||
} else {
|
|
||||||
retry = os_file_handle_error(name, operation);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
retry = false;
|
|
||||||
|
|
||||||
*success = true;
|
|
||||||
|
|
||||||
if (srv_use_native_aio && ((attributes & FILE_FLAG_OVERLAPPED) != 0)) {
|
|
||||||
/* Bind the file handle to completion port. Completion port
|
|
||||||
might not be created yet, in some stages of backup, but
|
|
||||||
must always be there for the server.*/
|
|
||||||
HANDLE port =(type == OS_LOG_FILE)?
|
|
||||||
log_completion_port : data_completion_port;
|
|
||||||
ut_a(port || srv_operation != SRV_OPERATION_NORMAL);
|
|
||||||
if (port) {
|
|
||||||
ut_a(CreateIoCompletionPort(file, port, 0, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} while (retry);
|
|
||||||
|
*success = (file != INVALID_HANDLE_VALUE);
|
||||||
|
if (*success) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
operation = (create_mode == OS_FILE_CREATE && !read_only) ?
|
||||||
|
"create" : "open";
|
||||||
|
|
||||||
|
if (on_error_no_exit) {
|
||||||
|
retry = os_file_handle_error_no_exit(
|
||||||
|
name, operation, on_error_silent);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
retry = os_file_handle_error(name, operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!retry) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*success && srv_use_native_aio && (attributes & FILE_FLAG_OVERLAPPED)) {
|
||||||
|
/* Bind the file handle to completion port. Completion port
|
||||||
|
might not be created yet, in some stages of backup, but
|
||||||
|
must always be there for the server.*/
|
||||||
|
HANDLE port = (type == OS_LOG_FILE) ?
|
||||||
|
log_completion_port : data_completion_port;
|
||||||
|
ut_a(port || srv_operation != SRV_OPERATION_NORMAL);
|
||||||
|
if (port) {
|
||||||
|
ut_a(CreateIoCompletionPort(file, port, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return(file);
|
return(file);
|
||||||
}
|
}
|
||||||
|
@ -3863,7 +3863,7 @@ row_ins_step(
|
|||||||
/* No-rollback tables should only be written to by a
|
/* No-rollback tables should only be written to by a
|
||||||
single thread at a time, but there can be multiple
|
single thread at a time, but there can be multiple
|
||||||
concurrent readers. We must hold an open table handle. */
|
concurrent readers. We must hold an open table handle. */
|
||||||
DBUG_ASSERT(node->table->n_ref_count > 0);
|
DBUG_ASSERT(node->table->get_ref_count() > 0);
|
||||||
DBUG_ASSERT(node->ins_type == INS_DIRECT);
|
DBUG_ASSERT(node->ins_type == INS_DIRECT);
|
||||||
/* No-rollback tables can consist only of a single index. */
|
/* No-rollback tables can consist only of a single index. */
|
||||||
DBUG_ASSERT(UT_LIST_GET_LEN(node->entry_list) == 1);
|
DBUG_ASSERT(UT_LIST_GET_LEN(node->entry_list) == 1);
|
||||||
|
@ -329,8 +329,8 @@ row_log_online_op(
|
|||||||
|
|
||||||
ut_ad(dtuple_validate(tuple));
|
ut_ad(dtuple_validate(tuple));
|
||||||
ut_ad(dtuple_get_n_fields(tuple) == dict_index_get_n_fields(index));
|
ut_ad(dtuple_get_n_fields(tuple) == dict_index_get_n_fields(index));
|
||||||
ut_ad(rw_lock_own(dict_index_get_lock(index), RW_LOCK_S)
|
ut_ad(rw_lock_own_flagged(&index->lock,
|
||||||
|| rw_lock_own(dict_index_get_lock(index), RW_LOCK_X));
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
|
|
||||||
if (index->is_corrupted()) {
|
if (index->is_corrupted()) {
|
||||||
return;
|
return;
|
||||||
|
@ -136,7 +136,8 @@ row_purge_remove_clust_if_poss_low(
|
|||||||
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
||||||
rec_offs_init(offsets_);
|
rec_offs_init(offsets_);
|
||||||
|
|
||||||
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S));
|
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S)
|
||||||
|
|| node->vcol_info.is_used());
|
||||||
|
|
||||||
index = dict_table_get_first_index(node->table);
|
index = dict_table_get_first_index(node->table);
|
||||||
|
|
||||||
@ -230,8 +231,55 @@ row_purge_remove_clust_if_poss(
|
|||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************//**
|
/** Tries to store secondary index cursor before openin mysql table for
|
||||||
Determines if it is possible to remove a secondary index entry.
|
virtual index condition computation.
|
||||||
|
@param[in,out] node row purge node
|
||||||
|
@param[in] index secondary index
|
||||||
|
@param[in,out] sec_pcur secondary index cursor
|
||||||
|
@param[in,out] sec_mtr mini-transaction which holds
|
||||||
|
secondary index entry */
|
||||||
|
static void row_purge_store_vsec_cur(
|
||||||
|
purge_node_t* node,
|
||||||
|
dict_index_t* index,
|
||||||
|
btr_pcur_t* sec_pcur,
|
||||||
|
mtr_t* sec_mtr)
|
||||||
|
{
|
||||||
|
row_purge_reposition_pcur(BTR_SEARCH_LEAF, node, sec_mtr);
|
||||||
|
|
||||||
|
if (!node->found_clust) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->vcol_info.set_requested();
|
||||||
|
|
||||||
|
btr_pcur_store_position(sec_pcur, sec_mtr);
|
||||||
|
|
||||||
|
btr_pcurs_commit_specify_mtr(&node->pcur, sec_pcur, sec_mtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Tries to restore secondary index cursor after opening the mysql table
|
||||||
|
@param[in,out] node row purge node
|
||||||
|
@param[in] index secondary index
|
||||||
|
@param[in,out] sec_mtr mini-transaction which holds secondary index entry
|
||||||
|
@param[in] is_tree true=pessimistic purge,
|
||||||
|
false=optimistic (leaf-page only)
|
||||||
|
@return false in case of restore failure. */
|
||||||
|
static bool row_purge_restore_vsec_cur(
|
||||||
|
purge_node_t* node,
|
||||||
|
dict_index_t* index,
|
||||||
|
btr_pcur_t* sec_pcur,
|
||||||
|
mtr_t* sec_mtr,
|
||||||
|
bool is_tree)
|
||||||
|
{
|
||||||
|
sec_mtr->start();
|
||||||
|
index->set_modified(*sec_mtr);
|
||||||
|
|
||||||
|
return btr_pcur_restore_position(
|
||||||
|
is_tree ? BTR_PURGE_TREE : BTR_PURGE_LEAF,
|
||||||
|
sec_pcur, sec_mtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Determines if it is possible to remove a secondary index entry.
|
||||||
Removal is possible if the secondary index entry does not refer to any
|
Removal is possible if the secondary index entry does not refer to any
|
||||||
not delete marked version of a clustered index record where DB_TRX_ID
|
not delete marked version of a clustered index record where DB_TRX_ID
|
||||||
is newer than the purge view.
|
is newer than the purge view.
|
||||||
@ -244,34 +292,95 @@ inserts a record that the secondary index entry would refer to.
|
|||||||
However, in that case, the user transaction would also re-insert the
|
However, in that case, the user transaction would also re-insert the
|
||||||
secondary index entry after purge has removed it and released the leaf
|
secondary index entry after purge has removed it and released the leaf
|
||||||
page latch.
|
page latch.
|
||||||
|
@param[in,out] node row purge node
|
||||||
|
@param[in] index secondary index
|
||||||
|
@param[in] entry secondary index entry
|
||||||
|
@param[in,out] sec_pcur secondary index cursor or NULL
|
||||||
|
if it is called for purge buffering
|
||||||
|
operation.
|
||||||
|
@param[in,out] sec_mtr mini-transaction which holds
|
||||||
|
secondary index entry or NULL if it is
|
||||||
|
called for purge buffering operation.
|
||||||
|
@param[in] is_tree true=pessimistic purge,
|
||||||
|
false=optimistic (leaf-page only)
|
||||||
@return true if the secondary index record can be purged */
|
@return true if the secondary index record can be purged */
|
||||||
bool
|
bool
|
||||||
row_purge_poss_sec(
|
row_purge_poss_sec(
|
||||||
/*===============*/
|
purge_node_t* node,
|
||||||
purge_node_t* node, /*!< in/out: row purge node */
|
dict_index_t* index,
|
||||||
dict_index_t* index, /*!< in: secondary index */
|
const dtuple_t* entry,
|
||||||
const dtuple_t* entry) /*!< in: secondary index entry */
|
btr_pcur_t* sec_pcur,
|
||||||
|
mtr_t* sec_mtr,
|
||||||
|
bool is_tree)
|
||||||
{
|
{
|
||||||
bool can_delete;
|
bool can_delete;
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
|
|
||||||
ut_ad(!dict_index_is_clust(index));
|
ut_ad(!dict_index_is_clust(index));
|
||||||
|
|
||||||
|
const bool store_cur = sec_mtr && !node->vcol_info.is_used()
|
||||||
|
&& dict_index_has_virtual(index);
|
||||||
|
|
||||||
|
if (store_cur) {
|
||||||
|
row_purge_store_vsec_cur(node, index, sec_pcur, sec_mtr);
|
||||||
|
ut_ad(sec_mtr->has_committed()
|
||||||
|
== node->vcol_info.is_requested());
|
||||||
|
|
||||||
|
/* The PRIMARY KEY value was not found in the clustered
|
||||||
|
index. The secondary index record found. We can purge
|
||||||
|
the secondary index record. */
|
||||||
|
if (!node->vcol_info.is_requested()) {
|
||||||
|
ut_ad(!node->found_clust);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
retry_purge_sec:
|
||||||
mtr_start(&mtr);
|
mtr_start(&mtr);
|
||||||
|
|
||||||
can_delete = !row_purge_reposition_pcur(BTR_SEARCH_LEAF, node, &mtr)
|
can_delete = !row_purge_reposition_pcur(BTR_SEARCH_LEAF, node, &mtr)
|
||||||
|| !row_vers_old_has_index_entry(TRUE,
|
|| !row_vers_old_has_index_entry(true,
|
||||||
btr_pcur_get_rec(&node->pcur),
|
btr_pcur_get_rec(&node->pcur),
|
||||||
&mtr, index, entry,
|
&mtr, index, entry,
|
||||||
node->roll_ptr, node->trx_id);
|
node->roll_ptr, node->trx_id,
|
||||||
|
&node->vcol_info);
|
||||||
|
|
||||||
|
if (node->vcol_info.is_first_fetch()) {
|
||||||
|
ut_ad(store_cur);
|
||||||
|
|
||||||
|
const TABLE* t= node->vcol_info.table();
|
||||||
|
DBUG_LOG("purge", "retry " << t
|
||||||
|
<< (is_tree ? " tree" : " leaf")
|
||||||
|
<< index->name << "," << index->table->name
|
||||||
|
<< ": " << rec_printer(entry).str());
|
||||||
|
|
||||||
|
ut_ad(mtr.has_committed());
|
||||||
|
|
||||||
|
if (t) {
|
||||||
|
node->vcol_info.set_used();
|
||||||
|
goto retry_purge_sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
node->table = NULL;
|
||||||
|
sec_pcur = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Persistent cursor is closed if reposition fails. */
|
/* Persistent cursor is closed if reposition fails. */
|
||||||
if (node->found_clust) {
|
if (node->found_clust) {
|
||||||
btr_pcur_commit_specify_mtr(&node->pcur, &mtr);
|
btr_pcur_commit_specify_mtr(&node->pcur, &mtr);
|
||||||
} else {
|
} else {
|
||||||
mtr_commit(&mtr);
|
mtr.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
return(can_delete);
|
ut_ad(mtr.has_committed());
|
||||||
|
|
||||||
|
if (store_cur && !row_purge_restore_vsec_cur(
|
||||||
|
node, index, sec_pcur, sec_mtr, is_tree)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return can_delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************************************
|
/***************************************************************
|
||||||
@ -287,7 +396,6 @@ row_purge_remove_sec_if_poss_tree(
|
|||||||
const dtuple_t* entry) /*!< in: index entry */
|
const dtuple_t* entry) /*!< in: index entry */
|
||||||
{
|
{
|
||||||
btr_pcur_t pcur;
|
btr_pcur_t pcur;
|
||||||
btr_cur_t* btr_cur;
|
|
||||||
ibool success = TRUE;
|
ibool success = TRUE;
|
||||||
dberr_t err;
|
dberr_t err;
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
@ -348,16 +456,16 @@ row_purge_remove_sec_if_poss_tree(
|
|||||||
ut_error;
|
ut_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
btr_cur = btr_pcur_get_btr_cur(&pcur);
|
|
||||||
|
|
||||||
/* We should remove the index record if no later version of the row,
|
/* We should remove the index record if no later version of the row,
|
||||||
which cannot be purged yet, requires its existence. If some requires,
|
which cannot be purged yet, requires its existence. If some requires,
|
||||||
we should do nothing. */
|
we should do nothing. */
|
||||||
|
|
||||||
if (row_purge_poss_sec(node, index, entry)) {
|
if (row_purge_poss_sec(node, index, entry, &pcur, &mtr, true)) {
|
||||||
|
|
||||||
/* Remove the index record, which should have been
|
/* Remove the index record, which should have been
|
||||||
marked for deletion. */
|
marked for deletion. */
|
||||||
if (!rec_get_deleted_flag(btr_cur_get_rec(btr_cur),
|
if (!rec_get_deleted_flag(btr_cur_get_rec(
|
||||||
|
btr_pcur_get_btr_cur(&pcur)),
|
||||||
dict_table_is_comp(index->table))) {
|
dict_table_is_comp(index->table))) {
|
||||||
ib::error()
|
ib::error()
|
||||||
<< "tried to purge non-delete-marked record"
|
<< "tried to purge non-delete-marked record"
|
||||||
@ -365,15 +473,18 @@ row_purge_remove_sec_if_poss_tree(
|
|||||||
<< " of table " << index->table->name
|
<< " of table " << index->table->name
|
||||||
<< ": tuple: " << *entry
|
<< ": tuple: " << *entry
|
||||||
<< ", record: " << rec_index_print(
|
<< ", record: " << rec_index_print(
|
||||||
btr_cur_get_rec(btr_cur), index);
|
btr_cur_get_rec(
|
||||||
|
btr_pcur_get_btr_cur(&pcur)),
|
||||||
|
index);
|
||||||
|
|
||||||
ut_ad(0);
|
ut_ad(0);
|
||||||
|
|
||||||
goto func_exit;
|
goto func_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
btr_cur_pessimistic_delete(&err, FALSE, btr_cur, 0,
|
btr_cur_pessimistic_delete(&err, FALSE,
|
||||||
false, &mtr);
|
btr_pcur_get_btr_cur(&pcur),
|
||||||
|
0, false, &mtr);
|
||||||
switch (UNIV_EXPECT(err, DB_SUCCESS)) {
|
switch (UNIV_EXPECT(err, DB_SUCCESS)) {
|
||||||
case DB_SUCCESS:
|
case DB_SUCCESS:
|
||||||
break;
|
break;
|
||||||
@ -385,6 +496,13 @@ row_purge_remove_sec_if_poss_tree(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node->vcol_op_failed()) {
|
||||||
|
ut_ad(mtr.has_committed());
|
||||||
|
ut_ad(!pcur.old_rec_buf);
|
||||||
|
ut_ad(pcur.pos_state == BTR_PCUR_NOT_POSITIONED);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
func_exit:
|
func_exit:
|
||||||
btr_pcur_close(&pcur);
|
btr_pcur_close(&pcur);
|
||||||
func_exit_no_pcur:
|
func_exit_no_pcur:
|
||||||
@ -445,8 +563,10 @@ row_purge_remove_sec_if_poss_leaf(
|
|||||||
index->is_committed(). */
|
index->is_committed(). */
|
||||||
ut_ad(!dict_index_is_online_ddl(index));
|
ut_ad(!dict_index_is_online_ddl(index));
|
||||||
|
|
||||||
/* Change buffering is disabled for spatial index. */
|
/* Change buffering is disabled for spatial index and
|
||||||
mode = dict_index_is_spatial(index)
|
virtual index. */
|
||||||
|
mode = (dict_index_is_spatial(index)
|
||||||
|
|| dict_index_has_virtual(index))
|
||||||
? BTR_MODIFY_LEAF
|
? BTR_MODIFY_LEAF
|
||||||
: BTR_PURGE_LEAF;
|
: BTR_PURGE_LEAF;
|
||||||
}
|
}
|
||||||
@ -474,7 +594,7 @@ row_purge_remove_sec_if_poss_leaf(
|
|||||||
case ROW_FOUND:
|
case ROW_FOUND:
|
||||||
/* Before attempting to purge a record, check
|
/* Before attempting to purge a record, check
|
||||||
if it is safe to do so. */
|
if it is safe to do so. */
|
||||||
if (row_purge_poss_sec(node, index, entry)) {
|
if (row_purge_poss_sec(node, index, entry, &pcur, &mtr, false)) {
|
||||||
btr_cur_t* btr_cur = btr_pcur_get_btr_cur(&pcur);
|
btr_cur_t* btr_cur = btr_pcur_get_btr_cur(&pcur);
|
||||||
|
|
||||||
/* Only delete-marked records should be purged. */
|
/* Only delete-marked records should be purged. */
|
||||||
@ -540,6 +660,12 @@ row_purge_remove_sec_if_poss_leaf(
|
|||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node->vcol_op_failed()) {
|
||||||
|
btr_pcur_close(&pcur);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* (The index entry is still needed,
|
/* (The index entry is still needed,
|
||||||
or the deletion succeeded) */
|
or the deletion succeeded) */
|
||||||
/* fall through */
|
/* fall through */
|
||||||
@ -586,6 +712,10 @@ row_purge_remove_sec_if_poss(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
retry:
|
retry:
|
||||||
|
if (node->vcol_op_failed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
success = row_purge_remove_sec_if_poss_tree(node, index, entry);
|
success = row_purge_remove_sec_if_poss_tree(node, index, entry);
|
||||||
/* The delete operation may fail if we have little
|
/* The delete operation may fail if we have little
|
||||||
file space left: TODO: easiest to crash the database
|
file space left: TODO: easiest to crash the database
|
||||||
@ -652,6 +782,12 @@ row_purge_del_mark(
|
|||||||
node->row, NULL, node->index,
|
node->row, NULL, node->index,
|
||||||
heap, ROW_BUILD_FOR_PURGE);
|
heap, ROW_BUILD_FOR_PURGE);
|
||||||
row_purge_remove_sec_if_poss(node, node->index, entry);
|
row_purge_remove_sec_if_poss(node, node->index, entry);
|
||||||
|
|
||||||
|
if (node->vcol_op_failed()) {
|
||||||
|
mem_heap_free(heap);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
mem_heap_empty(heap);
|
mem_heap_empty(heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,11 +803,10 @@ row_purge_del_mark(
|
|||||||
whose old history can no longer be observed.
|
whose old history can no longer be observed.
|
||||||
@param[in,out] node purge node
|
@param[in,out] node purge node
|
||||||
@param[in,out] mtr mini-transaction (will be started and committed) */
|
@param[in,out] mtr mini-transaction (will be started and committed) */
|
||||||
static
|
static void row_purge_reset_trx_id(purge_node_t* node, mtr_t* mtr)
|
||||||
void
|
|
||||||
row_purge_reset_trx_id(purge_node_t* node, mtr_t* mtr)
|
|
||||||
{
|
{
|
||||||
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S));
|
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S)
|
||||||
|
|| node->vcol_info.is_used());
|
||||||
/* Reset DB_TRX_ID, DB_ROLL_PTR for old records. */
|
/* Reset DB_TRX_ID, DB_ROLL_PTR for old records. */
|
||||||
mtr->start();
|
mtr->start();
|
||||||
|
|
||||||
@ -746,7 +881,8 @@ row_purge_upd_exist_or_extern_func(
|
|||||||
{
|
{
|
||||||
mem_heap_t* heap;
|
mem_heap_t* heap;
|
||||||
|
|
||||||
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S));
|
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S)
|
||||||
|
|| node->vcol_info.is_used());
|
||||||
ut_ad(!node->table->skip_alter_undo);
|
ut_ad(!node->table->skip_alter_undo);
|
||||||
|
|
||||||
if (node->rec_type == TRX_UNDO_UPD_DEL_REC
|
if (node->rec_type == TRX_UNDO_UPD_DEL_REC
|
||||||
@ -1107,10 +1243,15 @@ row_purge(
|
|||||||
bool purged = row_purge_record(
|
bool purged = row_purge_record(
|
||||||
node, undo_rec, thr, updated_extern);
|
node, undo_rec, thr, updated_extern);
|
||||||
|
|
||||||
rw_lock_s_unlock(dict_operation_lock);
|
if (!node->vcol_info.is_used()) {
|
||||||
|
rw_lock_s_unlock(dict_operation_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
ut_ad(!rw_lock_own(dict_operation_lock, RW_LOCK_S));
|
||||||
|
|
||||||
if (purged
|
if (purged
|
||||||
|| srv_shutdown_state != SRV_SHUTDOWN_NONE) {
|
|| srv_shutdown_state != SRV_SHUTDOWN_NONE
|
||||||
|
|| node->vcol_op_failed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1142,6 +1283,8 @@ row_purge_end(
|
|||||||
|
|
||||||
node->done = TRUE;
|
node->done = TRUE;
|
||||||
|
|
||||||
|
node->vcol_info.reset();
|
||||||
|
|
||||||
ut_a(thr->run_node != NULL);
|
ut_a(thr->run_node != NULL);
|
||||||
|
|
||||||
mem_heap_empty(node->heap);
|
mem_heap_empty(node->heap);
|
||||||
@ -1189,6 +1332,7 @@ row_purge_step(
|
|||||||
row_purge_end(thr);
|
row_purge_end(thr);
|
||||||
} else {
|
} else {
|
||||||
thr->run_node = node;
|
thr->run_node = node;
|
||||||
|
node->vcol_info.reset();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
row_purge_end(thr);
|
row_purge_end(thr);
|
||||||
|
@ -1100,8 +1100,8 @@ sel_set_rtr_rec_lock(
|
|||||||
rw_lock_x_lock(&(match->block.lock));
|
rw_lock_x_lock(&(match->block.lock));
|
||||||
retry:
|
retry:
|
||||||
cur_block = btr_pcur_get_block(pcur);
|
cur_block = btr_pcur_get_block(pcur);
|
||||||
ut_ad(rw_lock_own(&(match->block.lock), RW_LOCK_X)
|
ut_ad(rw_lock_own_flagged(&match->block.lock,
|
||||||
|| rw_lock_own(&(match->block.lock), RW_LOCK_S));
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
ut_ad(page_is_leaf(buf_block_get_frame(cur_block)));
|
ut_ad(page_is_leaf(buf_block_get_frame(cur_block)));
|
||||||
|
|
||||||
err = lock_sec_rec_read_check_and_lock(
|
err = lock_sec_rec_read_check_and_lock(
|
||||||
|
@ -1757,6 +1757,8 @@ row_truncate_table_for_mysql(
|
|||||||
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
|
trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG_SYNC_C("row_trunc_before_dict_lock");
|
||||||
|
|
||||||
/* Step-3: Validate ownership of needed locks (Exclusive lock).
|
/* Step-3: Validate ownership of needed locks (Exclusive lock).
|
||||||
Ownership will also ensure there is no active SQL queries, INSERT,
|
Ownership will also ensure there is no active SQL queries, INSERT,
|
||||||
SELECT, .....*/
|
SELECT, .....*/
|
||||||
|
@ -222,8 +222,8 @@ row_undo_mod_clust(
|
|||||||
ut_ad(thr_get_trx(thr) == node->trx);
|
ut_ad(thr_get_trx(thr) == node->trx);
|
||||||
ut_ad(node->trx->dict_operation_lock_mode);
|
ut_ad(node->trx->dict_operation_lock_mode);
|
||||||
ut_ad(node->trx->in_rollback);
|
ut_ad(node->trx->in_rollback);
|
||||||
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S)
|
ut_ad(rw_lock_own_flagged(dict_operation_lock,
|
||||||
|| rw_lock_own(dict_operation_lock, RW_LOCK_X));
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
|
|
||||||
log_free_check();
|
log_free_check();
|
||||||
pcur = &node->pcur;
|
pcur = &node->pcur;
|
||||||
@ -543,7 +543,7 @@ row_undo_mod_del_mark_or_remove_sec_low(
|
|||||||
clustered index entry, because there is no MVCC or purge. */
|
clustered index entry, because there is no MVCC or purge. */
|
||||||
if (node->table->is_temporary()
|
if (node->table->is_temporary()
|
||||||
|| row_vers_old_has_index_entry(
|
|| row_vers_old_has_index_entry(
|
||||||
FALSE, btr_pcur_get_rec(&node->pcur),
|
false, btr_pcur_get_rec(&node->pcur),
|
||||||
&mtr_vers, index, entry, 0, 0)) {
|
&mtr_vers, index, entry, 0, 0)) {
|
||||||
err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG,
|
err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG,
|
||||||
btr_cur, TRUE, thr, &mtr);
|
btr_cur, TRUE, thr, &mtr);
|
||||||
|
@ -3093,9 +3093,7 @@ row_upd_clust_step(
|
|||||||
|
|
||||||
ulint mode;
|
ulint mode;
|
||||||
|
|
||||||
DEBUG_SYNC_C_IF_THD(
|
DEBUG_SYNC_C_IF_THD(trx->mysql_thd, "innodb_row_upd_clust_step_enter");
|
||||||
thr_get_trx(thr)->mysql_thd,
|
|
||||||
"innodb_row_upd_clust_step_enter");
|
|
||||||
|
|
||||||
if (dict_index_is_online_ddl(index)) {
|
if (dict_index_is_online_ddl(index)) {
|
||||||
ut_ad(node->table->id != DICT_INDEXES_ID);
|
ut_ad(node->table->id != DICT_INDEXES_ID);
|
||||||
@ -3157,10 +3155,11 @@ row_upd_clust_step(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_ad(index->table->no_rollback()
|
ut_ad(index->table->no_rollback() || index->table->is_temporary()
|
||||||
|| lock_trx_has_rec_x_lock(thr_get_trx(thr), index->table,
|
|| row_get_rec_trx_id(rec, index, offsets) == trx->id
|
||||||
btr_pcur_get_block(pcur),
|
|| lock_trx_has_expl_x_lock(trx, index->table,
|
||||||
page_rec_get_heap_no(rec)));
|
btr_pcur_get_block(pcur),
|
||||||
|
page_rec_get_heap_no(rec)));
|
||||||
|
|
||||||
/* NOTE: the following function calls will also commit mtr */
|
/* NOTE: the following function calls will also commit mtr */
|
||||||
|
|
||||||
|
@ -126,14 +126,22 @@ row_vers_impl_x_locked_low(
|
|||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
trx_t* trx = trx_sys.find(caller_trx, trx_id);
|
trx_t* trx;
|
||||||
|
|
||||||
if (trx == 0) {
|
if (trx_id == caller_trx->id) {
|
||||||
/* The transaction that modified or inserted clust_rec is no
|
trx = caller_trx;
|
||||||
longer active, or it is corrupt: no implicit lock on rec */
|
trx->reference();
|
||||||
lock_check_trx_id_sanity(trx_id, clust_rec, clust_index, clust_offsets);
|
} else {
|
||||||
mem_heap_free(heap);
|
trx = trx_sys.find(caller_trx, trx_id);
|
||||||
DBUG_RETURN(0);
|
if (trx == 0) {
|
||||||
|
/* The transaction that modified or inserted
|
||||||
|
clust_rec is no longer active, or it is
|
||||||
|
corrupt: no implicit lock on rec */
|
||||||
|
lock_check_trx_id_sanity(trx_id, clust_rec,
|
||||||
|
clust_index, clust_offsets);
|
||||||
|
mem_heap_free(heap);
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
comp = page_rec_is_comp(rec);
|
comp = page_rec_is_comp(rec);
|
||||||
@ -424,14 +432,16 @@ row_vers_impl_x_locked(
|
|||||||
@param[in,out] row the cluster index row in dtuple form
|
@param[in,out] row the cluster index row in dtuple form
|
||||||
@param[in] clust_index clustered index
|
@param[in] clust_index clustered index
|
||||||
@param[in] index the secondary index
|
@param[in] index the secondary index
|
||||||
@param[in] heap heap used to build virtual dtuple */
|
@param[in] heap heap used to build virtual dtuple
|
||||||
|
@param[in,out] vcol_info virtual column information. */
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
row_vers_build_clust_v_col(
|
row_vers_build_clust_v_col(
|
||||||
dtuple_t* row,
|
dtuple_t* row,
|
||||||
dict_index_t* clust_index,
|
dict_index_t* clust_index,
|
||||||
dict_index_t* index,
|
dict_index_t* index,
|
||||||
mem_heap_t* heap)
|
mem_heap_t* heap,
|
||||||
|
purge_vcol_info_t* vcol_info)
|
||||||
{
|
{
|
||||||
mem_heap_t* local_heap = NULL;
|
mem_heap_t* local_heap = NULL;
|
||||||
VCOL_STORAGE *vcol_storage= NULL;
|
VCOL_STORAGE *vcol_storage= NULL;
|
||||||
@ -441,12 +451,22 @@ row_vers_build_clust_v_col(
|
|||||||
|
|
||||||
ut_ad(dict_index_has_virtual(index));
|
ut_ad(dict_index_has_virtual(index));
|
||||||
|
|
||||||
|
if (vcol_info != NULL) {
|
||||||
|
vcol_info->set_used();
|
||||||
|
maria_table = vcol_info->table();
|
||||||
|
}
|
||||||
|
|
||||||
innobase_allocate_row_for_vcol(thd, index,
|
innobase_allocate_row_for_vcol(thd, index,
|
||||||
&local_heap,
|
&local_heap,
|
||||||
&maria_table,
|
&maria_table,
|
||||||
&record,
|
&record,
|
||||||
&vcol_storage);
|
&vcol_storage);
|
||||||
|
|
||||||
|
if (vcol_info && !vcol_info->table()) {
|
||||||
|
vcol_info->set_table(maria_table);
|
||||||
|
goto func_exit;
|
||||||
|
}
|
||||||
|
|
||||||
for (ulint i = 0; i < dict_index_get_n_fields(index); i++) {
|
for (ulint i = 0; i < dict_index_get_n_fields(index); i++) {
|
||||||
const dict_field_t* ind_field = dict_index_get_nth_field(
|
const dict_field_t* ind_field = dict_index_get_nth_field(
|
||||||
index, i);
|
index, i);
|
||||||
@ -464,6 +484,7 @@ row_vers_build_clust_v_col(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func_exit:
|
||||||
if (local_heap) {
|
if (local_heap) {
|
||||||
if (vcol_storage)
|
if (vcol_storage)
|
||||||
innobase_free_row_for_vcol(vcol_storage);
|
innobase_free_row_for_vcol(vcol_storage);
|
||||||
@ -485,16 +506,16 @@ row_vers_build_clust_v_col(
|
|||||||
static
|
static
|
||||||
void
|
void
|
||||||
row_vers_build_cur_vrow_low(
|
row_vers_build_cur_vrow_low(
|
||||||
bool in_purge,
|
bool in_purge,
|
||||||
const rec_t* rec,
|
const rec_t* rec,
|
||||||
dict_index_t* clust_index,
|
dict_index_t* clust_index,
|
||||||
ulint* clust_offsets,
|
ulint* clust_offsets,
|
||||||
dict_index_t* index,
|
dict_index_t* index,
|
||||||
roll_ptr_t roll_ptr,
|
roll_ptr_t roll_ptr,
|
||||||
trx_id_t trx_id,
|
trx_id_t trx_id,
|
||||||
mem_heap_t* v_heap,
|
mem_heap_t* v_heap,
|
||||||
const dtuple_t**vrow,
|
const dtuple_t** vrow,
|
||||||
mtr_t* mtr)
|
mtr_t* mtr)
|
||||||
{
|
{
|
||||||
const rec_t* version;
|
const rec_t* version;
|
||||||
rec_t* prev_version;
|
rec_t* prev_version;
|
||||||
@ -771,20 +792,22 @@ func_exit:
|
|||||||
@param[in,out] heap heap memory
|
@param[in,out] heap heap memory
|
||||||
@param[in,out] v_heap heap memory to keep virtual colum dtuple
|
@param[in,out] v_heap heap memory to keep virtual colum dtuple
|
||||||
@param[in] mtr mtr holding the latch on rec
|
@param[in] mtr mtr holding the latch on rec
|
||||||
|
@param[in,out] vcol_info virtual column information for purge thread
|
||||||
@return dtuple contains virtual column data */
|
@return dtuple contains virtual column data */
|
||||||
static
|
static
|
||||||
const dtuple_t*
|
const dtuple_t*
|
||||||
row_vers_build_cur_vrow(
|
row_vers_build_cur_vrow(
|
||||||
bool in_purge,
|
bool in_purge,
|
||||||
const rec_t* rec,
|
const rec_t* rec,
|
||||||
dict_index_t* clust_index,
|
dict_index_t* clust_index,
|
||||||
ulint** clust_offsets,
|
ulint** clust_offsets,
|
||||||
dict_index_t* index,
|
dict_index_t* index,
|
||||||
roll_ptr_t roll_ptr,
|
roll_ptr_t roll_ptr,
|
||||||
trx_id_t trx_id,
|
trx_id_t trx_id,
|
||||||
mem_heap_t* heap,
|
mem_heap_t* heap,
|
||||||
mem_heap_t* v_heap,
|
mem_heap_t* v_heap,
|
||||||
mtr_t* mtr)
|
mtr_t* mtr,
|
||||||
|
purge_vcol_info_t* vcol_info)
|
||||||
{
|
{
|
||||||
const dtuple_t* cur_vrow = NULL;
|
const dtuple_t* cur_vrow = NULL;
|
||||||
|
|
||||||
@ -804,8 +827,17 @@ row_vers_build_cur_vrow(
|
|||||||
rec, *clust_offsets,
|
rec, *clust_offsets,
|
||||||
NULL, NULL, NULL, NULL, heap);
|
NULL, NULL, NULL, NULL, heap);
|
||||||
|
|
||||||
|
if (vcol_info && !vcol_info->is_used()) {
|
||||||
|
mtr->commit();
|
||||||
|
}
|
||||||
|
|
||||||
row_vers_build_clust_v_col(
|
row_vers_build_clust_v_col(
|
||||||
row, clust_index, index, heap);
|
row, clust_index, index, heap, vcol_info);
|
||||||
|
|
||||||
|
if (vcol_info != NULL && vcol_info->is_first_fetch()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
cur_vrow = dtuple_copy(row, v_heap);
|
cur_vrow = dtuple_copy(row, v_heap);
|
||||||
dtuple_dup_v_fld(cur_vrow, v_heap);
|
dtuple_dup_v_fld(cur_vrow, v_heap);
|
||||||
} else {
|
} else {
|
||||||
@ -820,27 +852,34 @@ row_vers_build_cur_vrow(
|
|||||||
return(cur_vrow);
|
return(cur_vrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************//**
|
/** Finds out if a version of the record, where the version >= the current
|
||||||
Finds out if a version of the record, where the version >= the current
|
|
||||||
purge view, should have ientry as its secondary index entry. We check
|
purge view, should have ientry as its secondary index entry. We check
|
||||||
if there is any not delete marked version of the record where the trx
|
if there is any not delete marked version of the record where the trx
|
||||||
id >= purge view, and the secondary index entry and ientry are identified in
|
id >= purge view, and the secondary index entry == ientry; exactly in
|
||||||
the alphabetical ordering; exactly in this case we return TRUE.
|
this case we return TRUE.
|
||||||
|
@param[in] also_curr TRUE if also rec is included in the versions
|
||||||
|
to search; otherwise only versions prior
|
||||||
|
to it are searched
|
||||||
|
@param[in] rec record in the clustered index; the caller
|
||||||
|
must have a latch on the page
|
||||||
|
@param[in] mtr mtr holding the latch on rec; it will
|
||||||
|
also hold the latch on purge_view
|
||||||
|
@param[in] index secondary index
|
||||||
|
@param[in] ientry secondary index entry
|
||||||
|
@param[in] roll_ptr roll_ptr for the purge record
|
||||||
|
@param[in] trx_id transaction ID on the purging record
|
||||||
|
@param[in,out] vcol_info virtual column information for purge thread.
|
||||||
@return TRUE if earlier version should have */
|
@return TRUE if earlier version should have */
|
||||||
ibool
|
bool
|
||||||
row_vers_old_has_index_entry(
|
row_vers_old_has_index_entry(
|
||||||
/*=========================*/
|
bool also_curr,
|
||||||
ibool also_curr,/*!< in: TRUE if also rec is included in the
|
const rec_t* rec,
|
||||||
versions to search; otherwise only versions
|
mtr_t* mtr,
|
||||||
prior to it are searched */
|
dict_index_t* index,
|
||||||
const rec_t* rec, /*!< in: record in the clustered index; the
|
const dtuple_t* ientry,
|
||||||
caller must have a latch on the page */
|
roll_ptr_t roll_ptr,
|
||||||
mtr_t* mtr, /*!< in: mtr holding the latch on rec; it will
|
trx_id_t trx_id,
|
||||||
also hold the latch on purge_view */
|
purge_vcol_info_t* vcol_info)
|
||||||
dict_index_t* index, /*!< in: the secondary index */
|
|
||||||
const dtuple_t* ientry, /*!< in: the secondary index entry */
|
|
||||||
roll_ptr_t roll_ptr,/*!< in: roll_ptr for the purge record */
|
|
||||||
trx_id_t trx_id) /*!< in: transaction ID on the purging record */
|
|
||||||
{
|
{
|
||||||
const rec_t* version;
|
const rec_t* version;
|
||||||
rec_t* prev_version;
|
rec_t* prev_version;
|
||||||
@ -908,8 +947,18 @@ row_vers_old_has_index_entry(
|
|||||||
columns need to be computed */
|
columns need to be computed */
|
||||||
if (trx_undo_roll_ptr_is_insert(t_roll_ptr)
|
if (trx_undo_roll_ptr_is_insert(t_roll_ptr)
|
||||||
|| dbug_v_purge) {
|
|| dbug_v_purge) {
|
||||||
|
|
||||||
|
if (vcol_info && !vcol_info->is_used()) {
|
||||||
|
mtr->commit();
|
||||||
|
}
|
||||||
|
|
||||||
row_vers_build_clust_v_col(
|
row_vers_build_clust_v_col(
|
||||||
row, clust_index, index, heap);
|
row, clust_index, index, heap,
|
||||||
|
vcol_info);
|
||||||
|
|
||||||
|
if (vcol_info && vcol_info->is_first_fetch()) {
|
||||||
|
goto unsafe_to_purge;
|
||||||
|
}
|
||||||
|
|
||||||
entry = row_build_index_entry(
|
entry = row_build_index_entry(
|
||||||
row, ext, index, heap);
|
row, ext, index, heap);
|
||||||
@ -974,7 +1023,7 @@ safe_to_purge:
|
|||||||
if (v_heap) {
|
if (v_heap) {
|
||||||
mem_heap_free(v_heap);
|
mem_heap_free(v_heap);
|
||||||
}
|
}
|
||||||
return(TRUE);
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (dict_index_has_virtual(index)) {
|
} else if (dict_index_has_virtual(index)) {
|
||||||
@ -982,9 +1031,14 @@ safe_to_purge:
|
|||||||
deleted, but the previous version of it might not. We will
|
deleted, but the previous version of it might not. We will
|
||||||
need to get the virtual column data from undo record
|
need to get the virtual column data from undo record
|
||||||
associated with current cluster index */
|
associated with current cluster index */
|
||||||
|
|
||||||
cur_vrow = row_vers_build_cur_vrow(
|
cur_vrow = row_vers_build_cur_vrow(
|
||||||
also_curr, rec, clust_index, &clust_offsets,
|
also_curr, rec, clust_index, &clust_offsets,
|
||||||
index, roll_ptr, trx_id, heap, v_heap, mtr);
|
index, roll_ptr, trx_id, heap, v_heap, mtr, vcol_info);
|
||||||
|
|
||||||
|
if (vcol_info && vcol_info->is_first_fetch()) {
|
||||||
|
goto unsafe_to_purge;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
version = rec;
|
version = rec;
|
||||||
@ -1003,14 +1057,14 @@ safe_to_purge:
|
|||||||
|
|
||||||
if (!prev_version) {
|
if (!prev_version) {
|
||||||
/* Versions end here */
|
/* Versions end here */
|
||||||
|
unsafe_to_purge:
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
|
|
||||||
if (v_heap) {
|
if (v_heap) {
|
||||||
mem_heap_free(v_heap);
|
mem_heap_free(v_heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(FALSE);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
clust_offsets = rec_get_offsets(prev_version, clust_index,
|
clust_offsets = rec_get_offsets(prev_version, clust_index,
|
||||||
|
@ -35,6 +35,7 @@ Created 2012-08-21 Sunny Bains
|
|||||||
|
|
||||||
#include "ut0new.h"
|
#include "ut0new.h"
|
||||||
#include "srv0start.h"
|
#include "srv0start.h"
|
||||||
|
#include "fil0fil.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -910,19 +911,10 @@ LatchDebug::check_order(
|
|||||||
|
|
||||||
case SYNC_TREE_NODE:
|
case SYNC_TREE_NODE:
|
||||||
|
|
||||||
{
|
ut_a(find(latches, SYNC_FSP) == &fil_system.temp_space->latch
|
||||||
const latch_t* fsp_latch;
|
|| find(latches, SYNC_INDEX_TREE)
|
||||||
|
|| find(latches, SYNC_DICT_OPERATION)
|
||||||
fsp_latch = find(latches, SYNC_FSP);
|
|| basic_check(latches, level, SYNC_TREE_NODE - 1));
|
||||||
|
|
||||||
ut_a((fsp_latch != NULL
|
|
||||||
&& fsp_latch->is_temp_fsp())
|
|
||||||
|| find(latches, SYNC_INDEX_TREE) != 0
|
|
||||||
|| find(latches, SYNC_DICT_OPERATION)
|
|
||||||
|| basic_check(latches,
|
|
||||||
level, SYNC_TREE_NODE - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SYNC_TREE_NODE_NEW:
|
case SYNC_TREE_NODE_NEW:
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
Copyright (c) 2008, Google Inc.
|
Copyright (c) 2008, Google Inc.
|
||||||
Copyright (c) 2017, MariaDB Corporation.
|
Copyright (c) 2017, 2018, MariaDB Corporation.
|
||||||
|
|
||||||
Portions of this file contain modifications contributed and copyrighted by
|
Portions of this file contain modifications contributed and copyrighted by
|
||||||
Google, Inc. Those modifications are gratefully acknowledged and are described
|
Google, Inc. Those modifications are gratefully acknowledged and are described
|
||||||
@ -1092,12 +1092,12 @@ rw_lock_own_flagged(
|
|||||||
|
|
||||||
const rw_lock_debug_t* info = *it;
|
const rw_lock_debug_t* info = *it;
|
||||||
|
|
||||||
ut_ad(os_thread_eq(info->thread_id, os_thread_get_curr_id()));
|
if (info->pass) {
|
||||||
|
|
||||||
if (info->pass != 0) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ut_ad(os_thread_eq(info->thread_id, os_thread_get_curr_id()));
|
||||||
|
|
||||||
switch (info->lock_type) {
|
switch (info->lock_type) {
|
||||||
case RW_LOCK_S:
|
case RW_LOCK_S:
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
Copyright (c) 2017, MariaDB Corporation.
|
Copyright (c) 2017, 2018, MariaDB Corporation.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify it under
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
the terms of the GNU General Public License as published by the Free Software
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
@ -1468,26 +1468,20 @@ cache_select_table(
|
|||||||
trx_i_s_cache_t* cache, /*!< in: whole cache */
|
trx_i_s_cache_t* cache, /*!< in: whole cache */
|
||||||
enum i_s_table table) /*!< in: which table */
|
enum i_s_table table) /*!< in: which table */
|
||||||
{
|
{
|
||||||
i_s_table_cache_t* table_cache;
|
ut_ad(rw_lock_own_flagged(cache->rw_lock,
|
||||||
|
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
|
||||||
ut_ad(rw_lock_own(cache->rw_lock, RW_LOCK_S)
|
|
||||||
|| rw_lock_own(cache->rw_lock, RW_LOCK_X));
|
|
||||||
|
|
||||||
switch (table) {
|
switch (table) {
|
||||||
case I_S_INNODB_TRX:
|
case I_S_INNODB_TRX:
|
||||||
table_cache = &cache->innodb_trx;
|
return &cache->innodb_trx;
|
||||||
break;
|
|
||||||
case I_S_INNODB_LOCKS:
|
case I_S_INNODB_LOCKS:
|
||||||
table_cache = &cache->innodb_locks;
|
return &cache->innodb_locks;
|
||||||
break;
|
|
||||||
case I_S_INNODB_LOCK_WAITS:
|
case I_S_INNODB_LOCK_WAITS:
|
||||||
table_cache = &cache->innodb_lock_waits;
|
return &cache->innodb_lock_waits;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ut_error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return(table_cache);
|
ut_error;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************//**
|
/*******************************************************************//**
|
||||||
|
@ -761,7 +761,7 @@ trx_lists_init_at_db_start()
|
|||||||
for (undo = UT_LIST_GET_FIRST(rseg->undo_list);
|
for (undo = UT_LIST_GET_FIRST(rseg->undo_list);
|
||||||
undo != NULL;
|
undo != NULL;
|
||||||
undo = UT_LIST_GET_NEXT(undo_list, undo)) {
|
undo = UT_LIST_GET_NEXT(undo_list, undo)) {
|
||||||
trx_t *trx = trx_sys.rw_trx_hash.find(0, undo->trx_id);
|
trx_t *trx = trx_sys.find(0, undo->trx_id, false);
|
||||||
if (!trx) {
|
if (!trx) {
|
||||||
trx_resurrect(undo, rseg, start_time,
|
trx_resurrect(undo, rseg, start_time,
|
||||||
&rows_to_undo, false);
|
&rows_to_undo, false);
|
||||||
|
@ -358,7 +358,7 @@ ut_print_buf_hex(
|
|||||||
|
|
||||||
for (data = static_cast<const byte*>(buf), i = 0; i < len; i++) {
|
for (data = static_cast<const byte*>(buf), i = 0; i < len; i++) {
|
||||||
byte b = *data++;
|
byte b = *data++;
|
||||||
o << hexdigit[(int) b >> 16] << hexdigit[b & 15];
|
o << hexdigit[int(b) >> 4] << hexdigit[b & 15];
|
||||||
}
|
}
|
||||||
|
|
||||||
o << ")";
|
o << ")";
|
||||||
|
@ -412,9 +412,18 @@ delimiter //
|
|||||||
create procedure mysql.spider_plugin_installer()
|
create procedure mysql.spider_plugin_installer()
|
||||||
begin
|
begin
|
||||||
set @win_plugin := IF(@@version_compile_os like 'Win%', 1, 0);
|
set @win_plugin := IF(@@version_compile_os like 'Win%', 1, 0);
|
||||||
|
set @have_spider_i_s_plugin := 0;
|
||||||
|
select @have_spider_i_s_plugin := 1 from INFORMATION_SCHEMA.plugins where PLUGIN_NAME = 'SPIDER';
|
||||||
set @have_spider_plugin := 0;
|
set @have_spider_plugin := 0;
|
||||||
select @have_spider_plugin := 1 from INFORMATION_SCHEMA.plugins where PLUGIN_NAME = 'SPIDER';
|
select @have_spider_plugin := 1 from mysql.plugin where name = 'spider';
|
||||||
if @have_spider_plugin = 0 then
|
if @have_spider_i_s_plugin = 0 then
|
||||||
|
if @have_spider_plugin = 1 then
|
||||||
|
-- spider plugin is present in mysql.plugin but not in
|
||||||
|
-- information_schema.plugins. Remove spider plugin entry
|
||||||
|
-- in mysql.plugin first.
|
||||||
|
delete from mysql.plugin where name = 'spider';
|
||||||
|
end if;
|
||||||
|
-- Install spider plugin
|
||||||
if @win_plugin = 0 then
|
if @win_plugin = 0 then
|
||||||
install plugin spider soname 'ha_spider.so';
|
install plugin spider soname 'ha_spider.so';
|
||||||
else
|
else
|
||||||
@ -423,7 +432,16 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
set @have_spider_i_s_alloc_mem_plugin := 0;
|
set @have_spider_i_s_alloc_mem_plugin := 0;
|
||||||
select @have_spider_i_s_alloc_mem_plugin := 1 from INFORMATION_SCHEMA.plugins where PLUGIN_NAME = 'SPIDER_ALLOC_MEM';
|
select @have_spider_i_s_alloc_mem_plugin := 1 from INFORMATION_SCHEMA.plugins where PLUGIN_NAME = 'SPIDER_ALLOC_MEM';
|
||||||
|
set @have_spider_alloc_mem_plugin := 0;
|
||||||
|
select @have_spider_alloc_mem_plugin := 1 from mysql.plugin where name = 'spider_alloc_mem';
|
||||||
if @have_spider_i_s_alloc_mem_plugin = 0 then
|
if @have_spider_i_s_alloc_mem_plugin = 0 then
|
||||||
|
if @have_spider_alloc_mem_plugin = 1 then
|
||||||
|
-- spider_alloc_mem plugin is present in mysql.plugin but not in
|
||||||
|
-- information_schema.plugins. Remove spider_alloc_mem plugin entry
|
||||||
|
-- in mysql.plugin first.
|
||||||
|
delete from mysql.plugin where name = 'spider_alloc_mem';
|
||||||
|
end if;
|
||||||
|
-- Install spider_alloc_mem plugin
|
||||||
if @win_plugin = 0 then
|
if @win_plugin = 0 then
|
||||||
install plugin spider_alloc_mem soname 'ha_spider.so';
|
install plugin spider_alloc_mem soname 'ha_spider.so';
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user