merge from 5.5 main

This commit is contained in:
Bjorn Munch 2011-08-22 13:32:11 +02:00
commit 07366f2404
56 changed files with 1554 additions and 186 deletions

View File

@ -446,8 +446,9 @@ enum ha_base_keytype {
#define HA_ERR_FILE_TOO_SHORT 175 /* File too short */
#define HA_ERR_WRONG_CRC 176 /* Wrong CRC on page */
#define HA_ERR_TOO_MANY_CONCURRENT_TRXS 177 /*Too many active concurrent transactions */
#define HA_ERR_INDEX_COL_TOO_LONG 178 /* Index column length exceeds limit */
#define HA_ERR_LAST 178 /* Copy of last error nr */
#define HA_ERR_INDEX_COL_TOO_LONG 178 /* Index column length exceeds limit */
#define HA_ERR_INDEX_CORRUPT 179 /* Index corrupted */
#define HA_ERR_LAST 179 /* Copy of last error nr */
/* Number of different errors */
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)

View File

@ -0,0 +1,18 @@
CREATE TABLE bug59733(a INT AUTO_INCREMENT PRIMARY KEY,b CHAR(1))ENGINE=InnoDB;
INSERT INTO bug59733 VALUES(0,'x');
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
CREATE INDEX b ON bug59733 (b);
DELETE FROM bug59733 WHERE (a%100)=0;
DROP INDEX b ON bug59733;
CREATE INDEX b ON bug59733 (b);
DROP TABLE bug59733;

View File

@ -0,0 +1,81 @@
set names utf8;
CREATE TABLE corrupt_bit_test_ā(
a INT AUTO_INCREMENT PRIMARY KEY,
b CHAR(100),
c INT,
z INT,
INDEX(b))
ENGINE=InnoDB;
INSERT INTO corrupt_bit_test_ā VALUES(0,'x',1, 1);
CREATE UNIQUE INDEX idxā ON corrupt_bit_test_ā(c, b);
CREATE UNIQUE INDEX idxē ON corrupt_bit_test_ā(z, b);
SELECT * FROM corrupt_bit_test_ā;
a b c z
1 x 1 1
select @@unique_checks;
@@unique_checks
0
select @@innodb_change_buffering_debug;
@@innodb_change_buffering_debug
1
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1,z+1 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+10,z+10 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+20,z+20 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+50,z+50 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+100,z+100 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+200,z+200 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+400,z+400 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+800,z+800 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1600,z+1600 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+4000,z+4000 FROM corrupt_bit_test_ā;
select count(*) from corrupt_bit_test_ā;
count(*)
1024
CREATE INDEX idx3 ON corrupt_bit_test_ā(b, c);
INSERT INTO corrupt_bit_test_ā VALUES(13000,'x',1,1);
CREATE INDEX idx4 ON corrupt_bit_test_ā(b, z);
check table corrupt_bit_test_ā;
Table Op Msg_type Msg_text
test.corrupt_bit_test_ā check Warning InnoDB: The B-tree of index "idxā" is corrupted.
test.corrupt_bit_test_ā check Warning InnoDB: The B-tree of index "idxē" is corrupted.
test.corrupt_bit_test_ā check error Corrupt
select c from corrupt_bit_test_ā;
ERROR HY000: Incorrect key file for table 'corrupt_bit_test_ā'; try to repair it
select z from corrupt_bit_test_ā;
ERROR HY000: Incorrect key file for table 'corrupt_bit_test_ā'; try to repair it
show warnings;
Level Code Message
Warning 179 InnoDB: Index "idxē" for table "test"."corrupt_bit_test_ā" is marked as corrupted
Error 1034 Incorrect key file for table 'corrupt_bit_test_ā'; try to repair it
insert into corrupt_bit_test_ā values (10001, "a", 20001, 20001);
select * from corrupt_bit_test_ā use index(primary) where a = 10001;
a b c z
10001 a 20001 20001
begin;
insert into corrupt_bit_test_ā values (10002, "a", 20002, 20002);
delete from corrupt_bit_test_ā where a = 10001;
insert into corrupt_bit_test_ā values (10001, "a", 20001, 20001);
rollback;
drop index idxā on corrupt_bit_test_ā;
check table corrupt_bit_test_ā;
Table Op Msg_type Msg_text
test.corrupt_bit_test_ā check Warning InnoDB: Index "idxē" is marked as corrupted
test.corrupt_bit_test_ā check error Corrupt
set names utf8;
select z from corrupt_bit_test_ā;
ERROR HY000: Incorrect key file for table 'corrupt_bit_test_ā'; try to repair it
drop index idxē on corrupt_bit_test_ā;
select z from corrupt_bit_test_ā limit 10;
z
20001
1
1
2
11
12
21
22
31
32
drop table corrupt_bit_test_ā;
SET GLOBAL innodb_change_buffering_debug = 0;

View File

@ -0,0 +1,53 @@
#
# Bug #59733 Possible deadlock when buffered changes are to be discarded
# in buf_page_create
#
-- source include/have_innodb.inc
-- disable_query_log
# The flag innodb_change_buffering_debug is only available in debug builds.
# It instructs InnoDB to try to evict pages from the buffer pool when
# change buffering is possible, so that the change buffer will be used
# whenever possible.
-- error 0,ER_UNKNOWN_SYSTEM_VARIABLE
SET @innodb_change_buffering_debug_orig = @@innodb_change_buffering_debug;
-- error 0,ER_UNKNOWN_SYSTEM_VARIABLE
SET GLOBAL innodb_change_buffering_debug = 1;
-- enable_query_log
CREATE TABLE bug59733(a INT AUTO_INCREMENT PRIMARY KEY,b CHAR(1))ENGINE=InnoDB;
# Create enough rows for the table, so that the insert buffer will be
# used. There must be multiple index pages, because changes to the
# root page are never buffered.
INSERT INTO bug59733 VALUES(0,'x');
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
INSERT INTO bug59733 SELECT 0,b FROM bug59733;
# Create the secondary index for which changes will be buffered.
CREATE INDEX b ON bug59733 (b);
# This should be buffered, if innodb_change_buffering_debug = 1 is in effect.
DELETE FROM bug59733 WHERE (a%100)=0;
# Drop the index in order to get free pages with orphaned buffered changes.
DROP INDEX b ON bug59733;
# Create the index and attempt to reuse pages for which buffered changes exist.
CREATE INDEX b ON bug59733 (b);
DROP TABLE bug59733;
-- disable_query_log
-- error 0, ER_UNKNOWN_SYSTEM_VARIABLE
SET GLOBAL innodb_change_buffering_debug = @innodb_change_buffering_debug_orig;

View File

@ -0,0 +1,120 @@
#
# Test for persistent corrupt bit for corrupted index and table
#
-- source include/have_innodb.inc
# This test needs debug server
--source include/have_debug.inc
-- disable_query_log
# This test setup is extracted from bug56680.test:
# The flag innodb_change_buffering_debug is only available in debug builds.
# It instructs InnoDB to try to evict pages from the buffer pool when
# change buffering is possible, so that the change buffer will be used
# whenever possible.
-- error 0,ER_UNKNOWN_SYSTEM_VARIABLE
SET @innodb_change_buffering_debug_orig = @@innodb_change_buffering_debug;
-- error 0,ER_UNKNOWN_SYSTEM_VARIABLE
SET GLOBAL innodb_change_buffering_debug = 1;
# Turn off Unique Check to create corrupted index with dup key
SET UNIQUE_CHECKS=0;
-- enable_query_log
set names utf8;
CREATE TABLE corrupt_bit_test_ā(
a INT AUTO_INCREMENT PRIMARY KEY,
b CHAR(100),
c INT,
z INT,
INDEX(b))
ENGINE=InnoDB;
INSERT INTO corrupt_bit_test_ā VALUES(0,'x',1, 1);
# This is the first unique index we intend to corrupt
CREATE UNIQUE INDEX idxā ON corrupt_bit_test_ā(c, b);
# This is the second unique index we intend to corrupt
CREATE UNIQUE INDEX idxē ON corrupt_bit_test_ā(z, b);
SELECT * FROM corrupt_bit_test_ā;
select @@unique_checks;
select @@innodb_change_buffering_debug;
# Create enough rows for the table, so that the insert buffer will be
# used for modifying the secondary index page. There must be multiple
# index pages, because changes to the root page are never buffered.
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1,z+1 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+10,z+10 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+20,z+20 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+50,z+50 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+100,z+100 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+200,z+200 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+400,z+400 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+800,z+800 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1600,z+1600 FROM corrupt_bit_test_ā;
INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+4000,z+4000 FROM corrupt_bit_test_ā;
select count(*) from corrupt_bit_test_ā;
CREATE INDEX idx3 ON corrupt_bit_test_ā(b, c);
# Create a dup key error on index "idxē" and "idxā" by inserting a dup value
INSERT INTO corrupt_bit_test_ā VALUES(13000,'x',1,1);
# creating an index should succeed even if other secondary indexes are corrupted
CREATE INDEX idx4 ON corrupt_bit_test_ā(b, z);
# Check table will find the unique indexes corrupted
# with dup key
check table corrupt_bit_test_ā;
# This selection intend to use the corrupted index. Expect to fail
-- error ER_NOT_KEYFILE
select c from corrupt_bit_test_ā;
-- error ER_NOT_KEYFILE
select z from corrupt_bit_test_ā;
show warnings;
# Since corrupted index is a secondary index, we only disable such
# index and allow other DML to proceed
insert into corrupt_bit_test_ā values (10001, "a", 20001, 20001);
# This does not use the corrupted index, expect to succeed
select * from corrupt_bit_test_ā use index(primary) where a = 10001;
# Some more DMLs
begin;
insert into corrupt_bit_test_ā values (10002, "a", 20002, 20002);
delete from corrupt_bit_test_ā where a = 10001;
insert into corrupt_bit_test_ā values (10001, "a", 20001, 20001);
rollback;
# Drop one corrupted index before reboot
drop index idxā on corrupt_bit_test_ā;
check table corrupt_bit_test_ā;
set names utf8;
-- error ER_NOT_KEYFILE
select z from corrupt_bit_test_ā;
# Drop the corrupted index
drop index idxē on corrupt_bit_test_ā;
# Now select back to normal
select z from corrupt_bit_test_ā limit 10;
# Drop table
drop table corrupt_bit_test_ā;
-- error 0, ER_UNKNOWN_SYSTEM_VARIABLE
SET GLOBAL innodb_change_buffering_debug = 0;

View File

@ -11,7 +11,5 @@ There should be *no* long test name listed below:
select variable_name as `There should be *no* variables listed below:` from t2
left join t1 on variable_name=test_name where test_name is null;
There should be *no* variables listed below:
INNODB_LARGE_PREFIX
INNODB_LARGE_PREFIX
drop table t1;
drop table t2;

View File

@ -1,13 +1,29 @@
SET @start_global_value = @@global.innodb_file_per_table;
SELECT @start_global_value;
@start_global_value
0
'#---------------------BS_STVARS_028_01----------------------#'
SELECT COUNT(@@GLOBAL.innodb_file_per_table);
COUNT(@@GLOBAL.innodb_file_per_table)
1
1 Expected
'#---------------------BS_STVARS_028_02----------------------#'
SELECT COUNT(@@GLOBAL.innodb_file_per_table);
COUNT(@@GLOBAL.innodb_file_per_table)
SET @@global.innodb_file_per_table = 0;
SELECT @@global.innodb_file_per_table;
@@global.innodb_file_per_table
0
SET @@global.innodb_file_per_table ='On' ;
SELECT @@global.innodb_file_per_table;
@@global.innodb_file_per_table
1
SET @@global.innodb_file_per_table ='Off' ;
SELECT @@global.innodb_file_per_table;
@@global.innodb_file_per_table
0
SET @@global.innodb_file_per_table = 1;
SELECT @@global.innodb_file_per_table;
@@global.innodb_file_per_table
1
1 Expected
'#---------------------BS_STVARS_028_03----------------------#'
SELECT IF(@@GLOBAL.innodb_file_per_table,'ON','OFF') = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
@ -47,4 +63,7 @@ COUNT(@@GLOBAL.innodb_file_per_table)
1 Expected
SELECT innodb_file_per_table = @@SESSION.innodb_file_per_table;
ERROR 42S22: Unknown column 'innodb_file_per_table' in 'field list'
Expected error 'Readonly variable'
SET @@global.innodb_file_per_table = @start_global_value;
SELECT @@global.innodb_file_per_table;
@@global.innodb_file_per_table
0

View File

@ -0,0 +1,53 @@
'#---------------------BS_STVARS_031_01----------------------#'
SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
COUNT(@@GLOBAL.innodb_force_load_corrupted)
1
1 Expected
'#---------------------BS_STVARS_031_02----------------------#'
SET @@GLOBAL.innodb_force_load_corrupted=1;
ERROR HY000: Variable 'innodb_force_load_corrupted' is a read only variable
Expected error 'Read only variable'
SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
COUNT(@@GLOBAL.innodb_force_load_corrupted)
1
1 Expected
'#---------------------BS_STVARS_031_03----------------------#'
SELECT IF(@@GLOBAL.innodb_force_load_corrupted, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_force_load_corrupted';
IF(@@GLOBAL.innodb_force_load_corrupted, "ON", "OFF") = VARIABLE_VALUE
1
1 Expected
SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
COUNT(@@GLOBAL.innodb_force_load_corrupted)
1
1 Expected
SELECT COUNT(VARIABLE_VALUE)
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_force_load_corrupted';
COUNT(VARIABLE_VALUE)
1
1 Expected
'#---------------------BS_STVARS_031_04----------------------#'
SELECT @@innodb_force_load_corrupted = @@GLOBAL.innodb_force_load_corrupted;
@@innodb_force_load_corrupted = @@GLOBAL.innodb_force_load_corrupted
1
1 Expected
'#---------------------BS_STVARS_031_05----------------------#'
SELECT COUNT(@@innodb_force_load_corrupted);
COUNT(@@innodb_force_load_corrupted)
1
1 Expected
SELECT COUNT(@@local.innodb_force_load_corrupted);
ERROR HY000: Variable 'innodb_force_load_corrupted' is a GLOBAL variable
Expected error 'Variable is a GLOBAL variable'
SELECT COUNT(@@SESSION.innodb_force_load_corrupted);
ERROR HY000: Variable 'innodb_force_load_corrupted' is a GLOBAL variable
Expected error 'Variable is a GLOBAL variable'
SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
COUNT(@@GLOBAL.innodb_force_load_corrupted)
1
1 Expected
SELECT innodb_force_load_corrupted = @@SESSION.innodb_force_load_corrupted;
ERROR 42S22: Unknown column 'innodb_force_load_corrupted' in 'field list'
Expected error 'Readonly variable'

View File

@ -0,0 +1,92 @@
SET @start_global_value = @@global.innodb_large_prefix;
SELECT @start_global_value;
@start_global_value
0
Valid values are 'ON' and 'OFF'
select @@global.innodb_large_prefix in (0, 1);
@@global.innodb_large_prefix in (0, 1)
1
select @@global.innodb_large_prefix;
@@global.innodb_large_prefix
0
select @@session.innodb_large_prefix;
ERROR HY000: Variable 'innodb_large_prefix' is a GLOBAL variable
show global variables like 'innodb_large_prefix';
Variable_name Value
innodb_large_prefix OFF
show session variables like 'innodb_large_prefix';
Variable_name Value
innodb_large_prefix OFF
select * from information_schema.global_variables where variable_name='innodb_large_prefix';
VARIABLE_NAME VARIABLE_VALUE
INNODB_LARGE_PREFIX OFF
select * from information_schema.session_variables where variable_name='innodb_large_prefix';
VARIABLE_NAME VARIABLE_VALUE
INNODB_LARGE_PREFIX OFF
set global innodb_large_prefix='OFF';
select @@global.innodb_large_prefix;
@@global.innodb_large_prefix
0
select * from information_schema.global_variables where variable_name='innodb_large_prefix';
VARIABLE_NAME VARIABLE_VALUE
INNODB_LARGE_PREFIX OFF
select * from information_schema.session_variables where variable_name='innodb_large_prefix';
VARIABLE_NAME VARIABLE_VALUE
INNODB_LARGE_PREFIX OFF
set @@global.innodb_large_prefix=1;
select @@global.innodb_large_prefix;
@@global.innodb_large_prefix
1
select * from information_schema.global_variables where variable_name='innodb_large_prefix';
VARIABLE_NAME VARIABLE_VALUE
INNODB_LARGE_PREFIX ON
select * from information_schema.session_variables where variable_name='innodb_large_prefix';
VARIABLE_NAME VARIABLE_VALUE
INNODB_LARGE_PREFIX ON
set global innodb_large_prefix=0;
select @@global.innodb_large_prefix;
@@global.innodb_large_prefix
0
select * from information_schema.global_variables where variable_name='innodb_large_prefix';
VARIABLE_NAME VARIABLE_VALUE
INNODB_LARGE_PREFIX OFF
select * from information_schema.session_variables where variable_name='innodb_large_prefix';
VARIABLE_NAME VARIABLE_VALUE
INNODB_LARGE_PREFIX OFF
set @@global.innodb_large_prefix='ON';
select @@global.innodb_large_prefix;
@@global.innodb_large_prefix
1
select * from information_schema.global_variables where variable_name='innodb_large_prefix';
VARIABLE_NAME VARIABLE_VALUE
INNODB_LARGE_PREFIX ON
select * from information_schema.session_variables where variable_name='innodb_large_prefix';
VARIABLE_NAME VARIABLE_VALUE
INNODB_LARGE_PREFIX ON
set session innodb_large_prefix='OFF';
ERROR HY000: Variable 'innodb_large_prefix' is a GLOBAL variable and should be set with SET GLOBAL
set @@session.innodb_large_prefix='ON';
ERROR HY000: Variable 'innodb_large_prefix' is a GLOBAL variable and should be set with SET GLOBAL
set global innodb_large_prefix=1.1;
ERROR 42000: Incorrect argument type to variable 'innodb_large_prefix'
set global innodb_large_prefix=1e1;
ERROR 42000: Incorrect argument type to variable 'innodb_large_prefix'
set global innodb_large_prefix=2;
ERROR 42000: Variable 'innodb_large_prefix' can't be set to the value of '2'
NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643)
set global innodb_large_prefix=-3;
select @@global.innodb_large_prefix;
@@global.innodb_large_prefix
1
select * from information_schema.global_variables where variable_name='innodb_large_prefix';
VARIABLE_NAME VARIABLE_VALUE
INNODB_LARGE_PREFIX ON
select * from information_schema.session_variables where variable_name='innodb_large_prefix';
VARIABLE_NAME VARIABLE_VALUE
INNODB_LARGE_PREFIX ON
set global innodb_large_prefix='AUTO';
ERROR 42000: Variable 'innodb_large_prefix' can't be set to the value of 'AUTO'
SET @@global.innodb_large_prefix = @start_global_value;
SELECT @@global.innodb_large_prefix;
@@global.innodb_large_prefix
0

View File

@ -1,13 +1,21 @@
SET @start_global_value=@@global.innodb_lock_wait_timeout;
SELECT @start_global_value;
@start_global_value
50
'#---------------------BS_STVARS_032_01----------------------#'
SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
COUNT(@@GLOBAL.innodb_lock_wait_timeout)
1
1 Expected
'#---------------------BS_STVARS_032_02----------------------#'
SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
COUNT(@@GLOBAL.innodb_lock_wait_timeout)
1
1 Expected
SET global innodb_lock_wait_timeout=60;
SELECT @@global.innodb_lock_wait_timeout;
@@global.innodb_lock_wait_timeout
60
SET session innodb_lock_wait_timeout=60;
SELECT @@session.innodb_lock_wait_timeout;
@@session.innodb_lock_wait_timeout
60
'#---------------------BS_STVARS_032_03----------------------#'
SELECT @@GLOBAL.innodb_lock_wait_timeout = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
@ -47,4 +55,7 @@ COUNT(@@GLOBAL.innodb_lock_wait_timeout)
1 Expected
SELECT innodb_lock_wait_timeout = @@SESSION.innodb_lock_wait_timeout;
ERROR 42S22: Unknown column 'innodb_lock_wait_timeout' in 'field list'
Expected error 'Readonly variable'
SET @@global.innodb_lock_wait_timeout = @start_global_value;
SELECT @@global.innodb_lock_wait_timeout;
@@global.innodb_lock_wait_timeout
50

View File

@ -1,8 +1,7 @@
################# mysql-test\t\innodb_autoinc_lock_mode_basic.test ############
# #
# Variable Name: innodb_autoinc_lock_mode #
# Scope: GLOBAL #
# Access Type: Dynamic #
# Access Type: Static #
# Data Type: Numeric #
# Default Value: 1 #
# Range: 0,1,2 #

View File

@ -3,9 +3,9 @@
# Variable Name: innodb_fast_shutdown #
# Scope: GLOBAL #
# Access Type: Dynamic #
# Data Type: boolean #
# Data Type: numeric #
# Default Value: 1 #
# Valid Values: 0,1 #
# Valid Values: 0,1,2 #
# #
# #
# Creation Date: 2008-02-20 #

View File

@ -4,7 +4,7 @@
# #
# Variable Name: innodb_file_per_table #
# Scope: Global #
# Access Type: Static #
# Access Type: Dynamic #
# Data Type: boolean #
# #
# #
@ -24,6 +24,10 @@
--source include/have_innodb.inc
SET @start_global_value = @@global.innodb_file_per_table;
SELECT @start_global_value;
--echo '#---------------------BS_STVARS_028_01----------------------#'
####################################################################
# Displaying default value #
@ -37,11 +41,17 @@ SELECT COUNT(@@GLOBAL.innodb_file_per_table);
# Check if Value can set #
####################################################################
SELECT COUNT(@@GLOBAL.innodb_file_per_table);
--echo 1 Expected
SET @@global.innodb_file_per_table = 0;
SELECT @@global.innodb_file_per_table;
SET @@global.innodb_file_per_table ='On' ;
SELECT @@global.innodb_file_per_table;
SET @@global.innodb_file_per_table ='Off' ;
SELECT @@global.innodb_file_per_table;
SET @@global.innodb_file_per_table = 1;
SELECT @@global.innodb_file_per_table;
--echo '#---------------------BS_STVARS_028_03----------------------#'
#################################################################
@ -93,6 +103,10 @@ SELECT COUNT(@@GLOBAL.innodb_file_per_table);
--Error ER_BAD_FIELD_ERROR
SELECT innodb_file_per_table = @@SESSION.innodb_file_per_table;
--echo Expected error 'Readonly variable'
#
# Cleanup
#
SET @@global.innodb_file_per_table = @start_global_value;
SELECT @@global.innodb_file_per_table;

View File

@ -0,0 +1,102 @@
################## mysql-test\t\innodb_force_load_corrupted_basic.test #####
# #
# Variable Name: innodb_force_load_corrupted #
# Scope: Global #
# Access Type: Static #
# Data Type: boolean #
# #
# #
# Creation Date: 2008-02-07 #
# Author : Sharique Abdullah #
# #
# #
# Description:Test Cases of Dynamic System Variable innodb_force_load_corrupted#
# that checks the behavior of this variable in the following ways #
# * Value Check #
# * Scope Check #
# #
# Reference: http://dev.mysql.com/doc/refman/5.1/en/ #
# server-system-variables.html #
# #
###############################################################################
--source include/have_innodb.inc
--echo '#---------------------BS_STVARS_031_01----------------------#'
####################################################################
# Displaying default value #
####################################################################
SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
--echo 1 Expected
--echo '#---------------------BS_STVARS_031_02----------------------#'
####################################################################
# Check if Value can set #
####################################################################
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
SET @@GLOBAL.innodb_force_load_corrupted=1;
--echo Expected error 'Read only variable'
SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
--echo 1 Expected
--echo '#---------------------BS_STVARS_031_03----------------------#'
#################################################################
# Check if the value in GLOBAL Table matches value in variable #
#################################################################
SELECT IF(@@GLOBAL.innodb_force_load_corrupted, "ON", "OFF") = VARIABLE_VALUE
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_force_load_corrupted';
--echo 1 Expected
SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
--echo 1 Expected
SELECT COUNT(VARIABLE_VALUE)
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
WHERE VARIABLE_NAME='innodb_force_load_corrupted';
--echo 1 Expected
--echo '#---------------------BS_STVARS_031_04----------------------#'
################################################################################
# Check if accessing variable with and without GLOBAL point to same variable #
################################################################################
SELECT @@innodb_force_load_corrupted = @@GLOBAL.innodb_force_load_corrupted;
--echo 1 Expected
--echo '#---------------------BS_STVARS_031_05----------------------#'
################################################################################
# Check if innodb_force_load_corrupted can be accessed with and without @@ sign #
################################################################################
SELECT COUNT(@@innodb_force_load_corrupted);
--echo 1 Expected
--Error ER_INCORRECT_GLOBAL_LOCAL_VAR
SELECT COUNT(@@local.innodb_force_load_corrupted);
--echo Expected error 'Variable is a GLOBAL variable'
--Error ER_INCORRECT_GLOBAL_LOCAL_VAR
SELECT COUNT(@@SESSION.innodb_force_load_corrupted);
--echo Expected error 'Variable is a GLOBAL variable'
SELECT COUNT(@@GLOBAL.innodb_force_load_corrupted);
--echo 1 Expected
--Error ER_BAD_FIELD_ERROR
SELECT innodb_force_load_corrupted = @@SESSION.innodb_force_load_corrupted;
--echo Expected error 'Readonly variable'

View File

@ -54,5 +54,9 @@ select * from information_schema.global_variables where variable_name='innodb_io
set global innodb_io_capacity=100;
select @@global.innodb_io_capacity;
#
# cleanup
#
SET @@global.innodb_io_capacity = @start_global_value;
SELECT @@global.innodb_io_capacity;

View File

@ -0,0 +1,70 @@
# 2010-01-25 - Added
#
--source include/have_innodb.inc
SET @start_global_value = @@global.innodb_large_prefix;
SELECT @start_global_value;
#
# exists as global only
#
--echo Valid values are 'ON' and 'OFF'
select @@global.innodb_large_prefix in (0, 1);
select @@global.innodb_large_prefix;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
select @@session.innodb_large_prefix;
show global variables like 'innodb_large_prefix';
show session variables like 'innodb_large_prefix';
select * from information_schema.global_variables where variable_name='innodb_large_prefix';
select * from information_schema.session_variables where variable_name='innodb_large_prefix';
#
# show that it's writable
#
set global innodb_large_prefix='OFF';
select @@global.innodb_large_prefix;
select * from information_schema.global_variables where variable_name='innodb_large_prefix';
select * from information_schema.session_variables where variable_name='innodb_large_prefix';
set @@global.innodb_large_prefix=1;
select @@global.innodb_large_prefix;
select * from information_schema.global_variables where variable_name='innodb_large_prefix';
select * from information_schema.session_variables where variable_name='innodb_large_prefix';
set global innodb_large_prefix=0;
select @@global.innodb_large_prefix;
select * from information_schema.global_variables where variable_name='innodb_large_prefix';
select * from information_schema.session_variables where variable_name='innodb_large_prefix';
set @@global.innodb_large_prefix='ON';
select @@global.innodb_large_prefix;
select * from information_schema.global_variables where variable_name='innodb_large_prefix';
select * from information_schema.session_variables where variable_name='innodb_large_prefix';
--error ER_GLOBAL_VARIABLE
set session innodb_large_prefix='OFF';
--error ER_GLOBAL_VARIABLE
set @@session.innodb_large_prefix='ON';
#
# incorrect types
#
--error ER_WRONG_TYPE_FOR_VAR
set global innodb_large_prefix=1.1;
--error ER_WRONG_TYPE_FOR_VAR
set global innodb_large_prefix=1e1;
--error ER_WRONG_VALUE_FOR_VAR
set global innodb_large_prefix=2;
--echo NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643)
set global innodb_large_prefix=-3;
select @@global.innodb_large_prefix;
select * from information_schema.global_variables where variable_name='innodb_large_prefix';
select * from information_schema.session_variables where variable_name='innodb_large_prefix';
--error ER_WRONG_VALUE_FOR_VAR
set global innodb_large_prefix='AUTO';
#
# Cleanup
#
SET @@global.innodb_large_prefix = @start_global_value;
SELECT @@global.innodb_large_prefix;

View File

@ -3,13 +3,13 @@
################## mysql-test\t\innodb_lock_wait_timeout_basic.test ###########
# #
# Variable Name: innodb_lock_wait_timeout #
# Scope: Global #
# Access Type: Static #
# Scope: Global , Session #
# Access Type: Dynamic #
# Data Type: numeric #
# #
# #
# Creation Date: 2008-02-07 #
# Author : Sharique Abdullah #
# Author : Sharique Abdullah #
# #
# #
# Description:Test Cases of Dynamic System Variable innodb_lock_wait_timeout #
@ -24,6 +24,9 @@
--source include/have_innodb.inc
SET @start_global_value=@@global.innodb_lock_wait_timeout;
SELECT @start_global_value;
--echo '#---------------------BS_STVARS_032_01----------------------#'
####################################################################
# Displaying default value #
@ -37,11 +40,10 @@ SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
# Check if Value can set #
####################################################################
SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
--echo 1 Expected
SET global innodb_lock_wait_timeout=60;
SELECT @@global.innodb_lock_wait_timeout;
SET session innodb_lock_wait_timeout=60;
SELECT @@session.innodb_lock_wait_timeout;
--echo '#---------------------BS_STVARS_032_03----------------------#'
#################################################################
@ -89,6 +91,10 @@ SELECT COUNT(@@GLOBAL.innodb_lock_wait_timeout);
--Error ER_BAD_FIELD_ERROR
SELECT innodb_lock_wait_timeout = @@SESSION.innodb_lock_wait_timeout;
--echo Expected error 'Readonly variable'
#
# Cleanup
#
SET @@global.innodb_lock_wait_timeout = @start_global_value;
SELECT @@global.innodb_lock_wait_timeout;

View File

@ -4,8 +4,8 @@
# Scope: GLOBAL #
# Access Type: Dynamic #
# Data Type: Numeric #
# Default Value: 90 #
# Range: 0-1000 #
# Default Value: 75 #
# Range: 0-99 #
# #
# #
# Creation Date: 2008-02-07 #

View File

@ -81,7 +81,8 @@ static const char *handler_error_messages[]=
"File to short; Expected more data in file",
"Read page with wrong checksum",
"Too many active concurrent transactions",
"Index column length exceeds limit"
"Index column length exceeds limit",
"Index corrupted"
};
extern void my_handler_error_register(void);

View File

@ -358,6 +358,7 @@ int ha_init_errors(void)
SETMSG(HA_ERR_AUTOINC_ERANGE, ER_DEFAULT(ER_WARN_DATA_OUT_OF_RANGE));
SETMSG(HA_ERR_TOO_MANY_CONCURRENT_TRXS, ER_DEFAULT(ER_TOO_MANY_CONCURRENT_TRXS));
SETMSG(HA_ERR_INDEX_COL_TOO_LONG, ER_DEFAULT(ER_INDEX_COLUMN_TOO_LONG));
SETMSG(HA_ERR_INDEX_CORRUPT, ER_DEFAULT(ER_INDEX_CORRUPT));
/* Register the error messages for use with my_error(). */
return my_error_register(get_handler_errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
@ -2865,6 +2866,9 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_INDEX_COL_TOO_LONG:
textno= ER_INDEX_COLUMN_TOO_LONG;
break;
case HA_ERR_INDEX_CORRUPT:
textno= ER_INDEX_CORRUPT;
break;
default:
{
/* The error was "unknown" to this function.

View File

@ -6415,3 +6415,5 @@ ER_ERROR_IN_TRIGGER_BODY
ER_ERROR_IN_UNKNOWN_TRIGGER_BODY
eng "Unknown trigger has an error in its body: '%-.256s'"
ER_INDEX_CORRUPT
eng "Index %s is corrupted"

View File

@ -655,8 +655,8 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length,
const char *proc_info= thd->proc_info;
len= my_snprintf(header, sizeof(header),
"MySQL thread id %lu, query id %lu",
thd->thread_id, (ulong) thd->query_id);
"MySQL thread id %lu, OS thread handle 0x%lx, query id %lu",
thd->thread_id, (ulong) thd->real_id, (ulong) thd->query_id);
str.length(0);
str.append(header, len);

View File

@ -690,7 +690,8 @@ btr_root_block_get(
zip_size = dict_table_zip_size(index->table);
root_page_no = dict_index_get_page(index);
block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
index, mtr);
ut_a((ibool)!!page_is_comp(buf_block_get_frame(block))
== dict_table_is_comp(index->table));
#ifdef UNIV_BTR_DEBUG
@ -891,7 +892,7 @@ btr_page_alloc_for_ibuf(
dict_table_zip_size(index->table),
node_addr.page, RW_X_LATCH, mtr);
new_page = buf_block_get_frame(new_block);
buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
buf_block_dbg_add_level(new_block, SYNC_IBUF_TREE_NODE_NEW);
flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
new_page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE,
@ -1139,7 +1140,7 @@ btr_node_ptr_get_child(
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
return(btr_block_get(space, dict_table_zip_size(index->table),
page_no, RW_X_LATCH, mtr));
page_no, RW_X_LATCH, index, mtr));
}
/************************************************************//**
@ -1312,7 +1313,8 @@ btr_create(
space, 0,
IBUF_HEADER + IBUF_TREE_SEG_HEADER, mtr);
buf_block_dbg_add_level(ibuf_hdr_block, SYNC_TREE_NODE_NEW);
buf_block_dbg_add_level(
ibuf_hdr_block, SYNC_IBUF_TREE_NODE_NEW);
ut_ad(buf_block_get_page_no(ibuf_hdr_block)
== IBUF_HEADER_PAGE_NO);
@ -1350,10 +1352,9 @@ btr_create(
page_no = buf_block_get_page_no(block);
frame = buf_block_get_frame(block);
buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
if (type & DICT_IBUF) {
/* It is an insert buffer tree: initialize the free list */
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
@ -1361,6 +1362,8 @@ btr_create(
} else {
/* It is a non-ibuf tree: create a file segment for leaf
pages */
buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
if (!fseg_create(space, page_no,
PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) {
/* Not enough space for new segment, free root
@ -1432,7 +1435,8 @@ btr_free_but_not_root(
leaf_loop:
mtr_start(&mtr);
root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr);
root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
NULL, &mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
+ root, space));
@ -1454,7 +1458,8 @@ leaf_loop:
top_loop:
mtr_start(&mtr);
root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH, &mtr);
root = btr_page_get(space, zip_size, root_page_no, RW_X_LATCH,
NULL, &mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
+ root, space));
@ -1480,13 +1485,13 @@ btr_free_root(
ulint zip_size, /*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint root_page_no, /*!< in: root page number */
mtr_t* mtr) /*!< in: a mini-transaction which has already
been started */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
buf_block_t* block;
fseg_header_t* header;
block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
block = btr_block_get(space, zip_size, root_page_no, RW_X_LATCH,
NULL, mtr);
btr_search_drop_page_hash_index(block);
@ -2365,9 +2370,8 @@ btr_attach_half_pages(
/* Update page links of the level */
if (prev_page_no != FIL_NULL) {
buf_block_t* prev_block = btr_block_get(space, zip_size,
prev_page_no,
RW_X_LATCH, mtr);
buf_block_t* prev_block = btr_block_get(
space, zip_size, prev_page_no, RW_X_LATCH, index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(prev_block->frame) == page_is_comp(page));
ut_a(btr_page_get_next(prev_block->frame, mtr)
@ -2380,9 +2384,8 @@ btr_attach_half_pages(
}
if (next_page_no != FIL_NULL) {
buf_block_t* next_block = btr_block_get(space, zip_size,
next_page_no,
RW_X_LATCH, mtr);
buf_block_t* next_block = btr_block_get(
space, zip_size, next_page_no, RW_X_LATCH, index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_block->frame) == page_is_comp(page));
ut_a(btr_page_get_prev(next_block->frame, mtr)
@ -2804,17 +2807,42 @@ func_exit:
return(rec);
}
#ifdef UNIV_SYNC_DEBUG
/*************************************************************//**
Removes a page from the level list of pages.
@param space in: space where removed
@param zip_size in: compressed page size in bytes, or 0 for uncompressed
@param page in/out: page to remove
@param index in: index tree
@param mtr in/out: mini-transaction */
# define btr_level_list_remove(space,zip_size,page,index,mtr) \
btr_level_list_remove_func(space,zip_size,page,index,mtr)
#else /* UNIV_SYNC_DEBUG */
/*************************************************************//**
Removes a page from the level list of pages.
@param space in: space where removed
@param zip_size in: compressed page size in bytes, or 0 for uncompressed
@param page in/out: page to remove
@param index in: index tree
@param mtr in/out: mini-transaction */
# define btr_level_list_remove(space,zip_size,page,index,mtr) \
btr_level_list_remove_func(space,zip_size,page,mtr)
#endif /* UNIV_SYNC_DEBUG */
/*************************************************************//**
Removes a page from the level list of pages. */
static
static __attribute__((nonnull))
void
btr_level_list_remove(
/*==================*/
ulint space, /*!< in: space where removed */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
page_t* page, /*!< in: page to remove */
mtr_t* mtr) /*!< in: mtr */
btr_level_list_remove_func(
/*=======================*/
ulint space, /*!< in: space where removed */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
page_t* page, /*!< in/out: page to remove */
#ifdef UNIV_SYNC_DEBUG
const dict_index_t* index, /*!< in: index tree */
#endif /* UNIV_SYNC_DEBUG */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
ulint prev_page_no;
ulint next_page_no;
@ -2832,7 +2860,7 @@ btr_level_list_remove(
if (prev_page_no != FIL_NULL) {
buf_block_t* prev_block
= btr_block_get(space, zip_size, prev_page_no,
RW_X_LATCH, mtr);
RW_X_LATCH, index, mtr);
page_t* prev_page
= buf_block_get_frame(prev_block);
#ifdef UNIV_BTR_DEBUG
@ -2849,7 +2877,7 @@ btr_level_list_remove(
if (next_page_no != FIL_NULL) {
buf_block_t* next_block
= btr_block_get(space, zip_size, next_page_no,
RW_X_LATCH, mtr);
RW_X_LATCH, index, mtr);
page_t* next_page
= buf_block_get_frame(next_block);
#ifdef UNIV_BTR_DEBUG
@ -3175,7 +3203,7 @@ btr_compress(
if (is_left) {
merge_block = btr_block_get(space, zip_size, left_page_no,
RW_X_LATCH, mtr);
RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(merge_page, mtr)
@ -3184,7 +3212,7 @@ btr_compress(
} else if (right_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, right_page_no,
RW_X_LATCH, mtr);
RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_prev(merge_page, mtr)
@ -3273,7 +3301,7 @@ err_exit:
btr_search_drop_page_hash_index(block);
/* Remove the page from the level list */
btr_level_list_remove(space, zip_size, page, mtr);
btr_level_list_remove(space, zip_size, page, index, mtr);
btr_node_ptr_delete(index, block, mtr);
lock_update_merge_left(merge_block, orig_pred, block);
@ -3330,7 +3358,7 @@ err_exit:
#endif /* UNIV_BTR_DEBUG */
/* Remove the page from the level list */
btr_level_list_remove(space, zip_size, page, mtr);
btr_level_list_remove(space, zip_size, page, index, mtr);
/* Replace the address of the old child node (= page) with the
address of the merge page to the right */
@ -3522,7 +3550,7 @@ btr_discard_page(
if (left_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, left_page_no,
RW_X_LATCH, mtr);
RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(merge_page, mtr)
@ -3530,7 +3558,7 @@ btr_discard_page(
#endif /* UNIV_BTR_DEBUG */
} else if (right_page_no != FIL_NULL) {
merge_block = btr_block_get(space, zip_size, right_page_no,
RW_X_LATCH, mtr);
RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_prev(merge_page, mtr)
@ -3565,7 +3593,7 @@ btr_discard_page(
btr_node_ptr_delete(index, block, mtr);
/* Remove the page from the level list */
btr_level_list_remove(space, zip_size, page, mtr);
btr_level_list_remove(space, zip_size, page, index, mtr);
#ifdef UNIV_ZIP_DEBUG
{
page_zip_des_t* merge_page_zip
@ -4083,7 +4111,7 @@ loop:
if (right_page_no != FIL_NULL) {
const rec_t* right_rec;
right_block = btr_block_get(space, zip_size, right_page_no,
RW_X_LATCH, &mtr);
RW_X_LATCH, index, &mtr);
right_page = buf_block_get_frame(right_block);
if (UNIV_UNLIKELY(btr_page_get_prev(right_page, &mtr)
!= page_get_page_no(page))) {
@ -4309,7 +4337,7 @@ node_ptr_fails:
mtr_start(&mtr);
block = btr_block_get(space, zip_size, right_page_no,
RW_X_LATCH, &mtr);
RW_X_LATCH, index, &mtr);
page = buf_block_get_frame(block);
goto loop;

View File

@ -249,7 +249,8 @@ btr_cur_latch_leaves(
case BTR_SEARCH_LEAF:
case BTR_MODIFY_LEAF:
mode = latch_mode == BTR_SEARCH_LEAF ? RW_S_LATCH : RW_X_LATCH;
get_block = btr_block_get(space, zip_size, page_no, mode, mtr);
get_block = btr_block_get(
space, zip_size, page_no, mode, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
#endif /* UNIV_BTR_DEBUG */
@ -260,9 +261,9 @@ btr_cur_latch_leaves(
left_page_no = btr_page_get_prev(page, mtr);
if (left_page_no != FIL_NULL) {
get_block = btr_block_get(space, zip_size,
left_page_no,
RW_X_LATCH, mtr);
get_block = btr_block_get(
space, zip_size, left_page_no,
RW_X_LATCH, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame)
== page_is_comp(page));
@ -272,8 +273,9 @@ btr_cur_latch_leaves(
get_block->check_index_page_at_flush = TRUE;
}
get_block = btr_block_get(space, zip_size, page_no,
RW_X_LATCH, mtr);
get_block = btr_block_get(
space, zip_size, page_no,
RW_X_LATCH, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
#endif /* UNIV_BTR_DEBUG */
@ -282,9 +284,9 @@ btr_cur_latch_leaves(
right_page_no = btr_page_get_next(page, mtr);
if (right_page_no != FIL_NULL) {
get_block = btr_block_get(space, zip_size,
right_page_no,
RW_X_LATCH, mtr);
get_block = btr_block_get(
space, zip_size, right_page_no,
RW_X_LATCH, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame)
== page_is_comp(page));
@ -303,8 +305,9 @@ btr_cur_latch_leaves(
left_page_no = btr_page_get_prev(page, mtr);
if (left_page_no != FIL_NULL) {
get_block = btr_block_get(space, zip_size,
left_page_no, mode, mtr);
get_block = btr_block_get(
space, zip_size,
left_page_no, mode, cursor->index, mtr);
cursor->left_block = get_block;
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame)
@ -315,7 +318,8 @@ btr_cur_latch_leaves(
get_block->check_index_page_at_flush = TRUE;
}
get_block = btr_block_get(space, zip_size, page_no, mode, mtr);
get_block = btr_block_get(
space, zip_size, page_no, mode, cursor->index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame) == page_is_comp(page));
#endif /* UNIV_BTR_DEBUG */
@ -669,7 +673,9 @@ retry_page_get:
ut_a(!page_zip || page_zip_validate(page_zip, page));
#endif /* UNIV_ZIP_DEBUG */
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
buf_block_dbg_add_level(
block, dict_index_is_ibuf(index)
? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
}
ut_ad(index->id == btr_page_get_index_id(page));
@ -767,7 +773,7 @@ retry_page_get:
if (level != 0) {
/* x-latch the page */
page = btr_page_get(
space, zip_size, page_no, RW_X_LATCH, mtr);
space, zip_size, page_no, RW_X_LATCH, index, mtr);
ut_a((ibool)!!page_is_comp(page)
== dict_table_is_comp(index->table));

View File

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
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
@ -266,8 +266,10 @@ btr_pcur_restore_position_func(
file, line, mtr))) {
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
buf_block_dbg_add_level(btr_pcur_get_block(cursor),
SYNC_TREE_NODE);
buf_block_dbg_add_level(
btr_pcur_get_block(cursor),
dict_index_is_ibuf(index)
? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
if (cursor->rel_pos == BTR_PCUR_ON) {
#ifdef UNIV_DEBUG
@ -417,7 +419,8 @@ btr_pcur_move_to_next_page(
ut_ad(next_page_no != FIL_NULL);
next_block = btr_block_get(space, zip_size, next_page_no,
cursor->latch_mode, mtr);
cursor->latch_mode,
btr_pcur_get_btr_cur(cursor)->index, mtr);
next_page = buf_block_get_frame(next_block);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_page) == page_is_comp(page));

View File

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@ -845,6 +845,7 @@ btr_search_guess_on_hash(
btr_pcur_t pcur;
#endif
ut_ad(index && info && tuple && cursor && mtr);
ut_ad(!dict_index_is_ibuf(index));
ut_ad((latch_mode == BTR_SEARCH_LEAF)
|| (latch_mode == BTR_MODIFY_LEAF));

View File

@ -3473,6 +3473,53 @@ buf_page_create(
return(block);
}
/********************************************************************//**
Mark a table with the specified space pointed by bpage->space corrupted.
Also remove the bpage from LRU list.
@return TRUE if successful */
static
ibool
buf_mark_space_corrupt(
/*===================*/
buf_page_t* bpage) /*!< in: pointer to the block in question */
{
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
const ibool uncompressed = (buf_page_get_state(bpage)
== BUF_BLOCK_FILE_PAGE);
ulint space = bpage->space;
ibool ret = TRUE;
/* First unfix and release lock on the bpage */
buf_pool_mutex_enter(buf_pool);
mutex_enter(buf_page_get_mutex(bpage));
ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
ut_ad(bpage->buf_fix_count == 0);
/* Set BUF_IO_NONE before we remove the block from LRU list */
buf_page_set_io_fix(bpage, BUF_IO_NONE);
if (uncompressed) {
rw_lock_x_unlock_gen(
&((buf_block_t*) bpage)->lock,
BUF_IO_READ);
}
/* Find the table with specified space id, and mark it corrupted */
if (dict_set_corrupted_by_space(space)) {
buf_LRU_free_one_page(bpage);
} else {
ret = FALSE;
}
ut_ad(buf_pool->n_pend_reads > 0);
buf_pool->n_pend_reads--;
mutex_exit(buf_page_get_mutex(bpage));
buf_pool_mutex_exit(buf_pool);
return(ret);
}
/********************************************************************//**
Completes an asynchronous read or write request of a file page to or from
the buffer pool. */
@ -3598,10 +3645,19 @@ corrupt:
"InnoDB: about forcing recovery.\n", stderr);
if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
fputs("InnoDB: Ending processing because of"
" a corrupt database page.\n",
stderr);
exit(1);
/* If page space id is larger than TRX_SYS_SPACE
(0), we will attempt to mark the corresponding
table as corrupted instead of crashing server */
if (bpage->space > TRX_SYS_SPACE
&& buf_mark_space_corrupt(bpage)) {
return;
} else {
fputs("InnoDB: Ending processing"
" because of"
" a corrupt database page.\n",
stderr);
ut_error;
}
}
}

View File

@ -1885,6 +1885,22 @@ buf_LRU_block_free_hashed_page(
buf_LRU_block_free_non_file_page(block);
}
/******************************************************************//**
Remove one page from LRU list and put it to free list */
UNIV_INTERN
void
buf_LRU_free_one_page(
/*==================*/
buf_page_t* bpage) /*!< in/out: block, must contain a file page and
be in a state where it can be freed; there
may or may not be a hash index to the page */
{
if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
!= BUF_BLOCK_ZIP_FREE) {
buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
}
}
/**********************************************************************//**
Updates buf_pool->LRU_old_ratio for one buffer pool instance.
@return updated old_pct */

View File

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
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
@ -827,7 +827,7 @@ dict_truncate_index_tree(
appropriate field in the SYS_INDEXES record: this mini-transaction
marks the B-tree totally truncated */
btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, mtr);
btr_block_get(space, zip_size, root_page_no, RW_X_LATCH, NULL, mtr);
btr_free_root(space, zip_size, root_page_no, mtr);
create:

View File

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
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
@ -54,6 +54,7 @@ UNIV_INTERN dict_index_t* dict_ind_compact;
#include "row0merge.h"
#include "m_ctype.h" /* my_isspace() */
#include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/
#include "row0upd.h"
#include <ctype.h>
@ -611,8 +612,7 @@ dict_table_get_on_id(
{
dict_table_t* table;
if (table_id <= DICT_FIELDS_ID
|| trx->dict_operation_lock_mode == RW_X_LATCH) {
if (trx->dict_operation_lock_mode == RW_X_LATCH) {
/* Note: An X latch implies that the transaction
already owns the dictionary mutex. */
@ -1714,7 +1714,8 @@ undo_size_ok:
new_index->page = page_no;
rw_lock_create(index_tree_rw_lock_key, &new_index->lock,
SYNC_INDEX_TREE);
dict_index_is_ibuf(index)
? SYNC_IBUF_INDEX_TREE : SYNC_INDEX_TREE);
if (!UNIV_UNLIKELY(new_index->type & DICT_UNIVERSAL)) {
@ -5045,4 +5046,179 @@ dict_close(void)
rw_lock_free(&dict_table_stats_latches[i]);
}
}
/**********************************************************************//**
Find a table in dict_sys->table_LRU list with specified space id
@return table if found, NULL if not */
static
dict_table_t*
dict_find_table_by_space(
/*=====================*/
ulint space_id) /*!< in: space ID */
{
dict_table_t* table;
ulint num_item;
ulint count = 0;
ut_ad(space_id > 0);
table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
num_item = UT_LIST_GET_LEN(dict_sys->table_LRU);
/* This function intentionally does not acquire mutex as it is used
by error handling code in deep call stack as last means to avoid
killing the server, so it worth to risk some consequencies for
the action. */
while (table && count < num_item) {
if (table->space == space_id) {
return(table);
}
table = UT_LIST_GET_NEXT(table_LRU, table);
count++;
}
return(NULL);
}
/**********************************************************************//**
Flags a table with specified space_id corrupted in the data dictionary
cache
@return TRUE if successful */
UNIV_INTERN
ibool
dict_set_corrupted_by_space(
/*========================*/
ulint space_id) /*!< in: space ID */
{
dict_table_t* table;
table = dict_find_table_by_space(space_id);
if (!table) {
return(FALSE);
}
/* mark the table->corrupted bit only, since the caller
could be too deep in the stack for SYS_INDEXES update */
table->corrupted = TRUE;
return(TRUE);
}
/**********************************************************************//**
Flags an index corrupted both in the data dictionary cache
and in the SYS_INDEXES */
UNIV_INTERN
void
dict_set_corrupted(
/*===============*/
dict_index_t* index) /*!< in/out: index */
{
mem_heap_t* heap;
mtr_t mtr;
dict_index_t* sys_index;
dtuple_t* tuple;
dfield_t* dfield;
byte* buf;
const char* status;
btr_cur_t cursor;
ut_ad(index);
ut_ad(mutex_own(&dict_sys->mutex));
ut_ad(!dict_table_is_comp(dict_sys->sys_tables));
ut_ad(!dict_table_is_comp(dict_sys->sys_indexes));
#ifdef UNIV_SYNC_DEBUG
ut_ad(sync_thread_levels_empty_except_dict());
#endif
/* Mark the table as corrupted only if the clustered index
is corrupted */
if (dict_index_is_clust(index)) {
index->table->corrupted = TRUE;
}
if (UNIV_UNLIKELY(dict_index_is_corrupted(index))) {
/* The index was already flagged corrupted. */
ut_ad(index->table->corrupted);
return;
}
heap = mem_heap_create(sizeof(dtuple_t) + 2 * (sizeof(dfield_t)
+ sizeof(que_fork_t) + sizeof(upd_node_t)
+ sizeof(upd_t) + 12));
mtr_start(&mtr);
index->type |= DICT_CORRUPT;
sys_index = UT_LIST_GET_FIRST(dict_sys->sys_indexes->indexes);
/* Find the index row in SYS_INDEXES */
tuple = dtuple_create(heap, 2);
dfield = dtuple_get_nth_field(tuple, 0);
buf = mem_heap_alloc(heap, 8);
mach_write_to_8(buf, index->table->id);
dfield_set_data(dfield, buf, 8);
dfield = dtuple_get_nth_field(tuple, 1);
buf = mem_heap_alloc(heap, 8);
mach_write_to_8(buf, index->id);
dfield_set_data(dfield, buf, 8);
dict_index_copy_types(tuple, sys_index, 2);
btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE,
BTR_MODIFY_LEAF,
&cursor, 0, __FILE__, __LINE__, &mtr);
if (cursor.up_match == dtuple_get_n_fields(tuple)) {
/* UPDATE SYS_INDEXES SET TYPE=index->type
WHERE TABLE_ID=index->table->id AND INDEX_ID=index->id */
ulint len;
byte* field = rec_get_nth_field_old(
btr_cur_get_rec(&cursor),
DICT_SYS_INDEXES_TYPE_FIELD, &len);
if (len != 4) {
goto fail;
}
mlog_write_ulint(field, index->type, MLOG_4BYTES, &mtr);
status = " InnoDB: Flagged corruption of ";
} else {
fail:
status = " InnoDB: Unable to flag corruption of ";
}
mtr_commit(&mtr);
mem_heap_free(heap);
ut_print_timestamp(stderr);
fputs(status, stderr);
dict_index_name_print(stderr, NULL, index);
putc('\n', stderr);
}
/**********************************************************************//**
Flags an index corrupted in the data dictionary cache only. This
is used mostly to mark a corrupted index when index's own dictionary
is corrupted, and we force to load such index for repair purpose */
UNIV_INTERN
void
dict_set_corrupted_index_cache_only(
/*================================*/
dict_index_t* index) /*!< in/out: index */
{
ut_ad(index);
ut_ad(mutex_own(&dict_sys->mutex));
ut_ad(!dict_table_is_comp(dict_sys->sys_tables));
ut_ad(!dict_table_is_comp(dict_sys->sys_indexes));
/* Mark the table as corrupted only if the clustered index
is corrupted */
if (dict_index_is_clust(index)) {
index->table->corrupted = TRUE;
}
index->type |= DICT_CORRUPT;
}
#endif /* !UNIV_HOTBACKUP */

View File

@ -52,6 +52,11 @@ static const char* SYSTEM_TABLE_NAME[] = {
"SYS_FOREIGN",
"SYS_FOREIGN_COLS"
};
/* If this flag is TRUE, then we will load the cluster index's (and tables')
metadata even if it is marked as "corrupted". */
UNIV_INTERN my_bool srv_load_corrupted = FALSE;
/****************************************************************//**
Compare the name of an index column.
@return TRUE if the i'th column of index is 'name'. */
@ -1324,6 +1329,9 @@ err_len:
goto err_len;
}
type = mach_read_from_4(field);
if (UNIV_UNLIKELY(type & (~0 << DICT_IT_BITS))) {
return("unknown SYS_INDEXES.TYPE bits");
}
field = rec_get_nth_field_old(rec, 7/*SPACE*/, &len);
if (UNIV_UNLIKELY(len != 4)) {
@ -1423,16 +1431,47 @@ dict_load_indexes(
goto next_rec;
} else if (err_msg) {
fprintf(stderr, "InnoDB: %s\n", err_msg);
if (ignore_err & DICT_ERR_IGNORE_CORRUPT) {
goto next_rec;
}
error = DB_CORRUPTION;
goto func_exit;
}
ut_ad(index);
/* Check whether the index is corrupted */
if (dict_index_is_corrupted(index)) {
ut_print_timestamp(stderr);
fputs(" InnoDB: ", stderr);
dict_index_name_print(stderr, NULL, index);
fputs(" is corrupted\n", stderr);
if (!srv_load_corrupted
&& !(ignore_err & DICT_ERR_IGNORE_CORRUPT)
&& dict_index_is_clust(index)) {
dict_mem_index_free(index);
error = DB_INDEX_CORRUPT;
goto func_exit;
} else {
/* We will load the index if
1) srv_load_corrupted is TRUE
2) ignore_err is set with
DICT_ERR_IGNORE_CORRUPT
3) if the index corrupted is a secondary
index */
ut_print_timestamp(stderr);
fputs(" InnoDB: load corrupted index ", stderr);
dict_index_name_print(stderr, NULL, index);
putc('\n', stderr);
}
}
/* We check for unsupported types first, so that the
subsequent checks are relevant for the supported types. */
if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
if (index->type & ~(DICT_CLUSTERED | DICT_UNIQUE
| DICT_CORRUPT)) {
fprintf(stderr,
"InnoDB: Error: unknown type %lu"
" of index %s of table %s\n",
@ -1453,9 +1492,13 @@ dict_load_indexes(
/* If caller can tolerate this error,
we will continue to load the index and
let caller deal with this error. However
mark the index and table corrupted */
index->corrupted = TRUE;
table->corrupted = TRUE;
mark the index and table corrupted. We
only need to mark such in the index
dictionary cache for such metadata corruption,
since we would always be able to set it
when loading the dictionary cache */
dict_set_corrupted_index_cache_only(index);
fprintf(stderr,
"InnoDB: Index is corrupt but forcing"
" load into data dictionary\n");
@ -1495,9 +1538,10 @@ corrupted:
index->name, table->name);
/* If the force recovery flag is set, and
if the failed index is not the primary index, we
will continue and open other indexes */
if (srv_force_recovery
if the failed index is not the clustered index,
we will continue and open other indexes */
if ((srv_force_recovery
|| srv_load_corrupted)
&& !dict_index_is_clust(index)) {
error = DB_SUCCESS;
goto next_rec;
@ -1812,6 +1856,30 @@ err_exit:
err = dict_load_indexes(table, heap, ignore_err);
if (err == DB_INDEX_CORRUPT) {
/* Refuse to load the table if the table has a corrupted
cluster index */
if (!srv_load_corrupted) {
fprintf(stderr, "InnoDB: Error: Load table ");
ut_print_name(stderr, NULL, TRUE, table->name);
fprintf(stderr, " failed, the table has corrupted"
" clustered indexes. Turn on"
" 'innodb_force_load_corrupted'"
" to drop it\n");
dict_table_remove_from_cache(table);
table = NULL;
goto func_exit;
} else {
dict_index_t* clust_index;
clust_index = dict_table_get_first_index(table);
if (dict_index_is_corrupted(clust_index)) {
table->corrupted = TRUE;
}
}
}
/* Initialize table foreign_child value. Its value could be
changed when dict_load_foreigns() is called below */
table->fk_max_recusive_level = 0;
@ -1838,9 +1906,15 @@ err_exit:
index = dict_table_get_first_index(table);
if (!srv_force_recovery || !index
|| !dict_index_is_clust(index)) {
|| !dict_index_is_clust(index)) {
dict_table_remove_from_cache(table);
table = NULL;
} else if (dict_index_is_corrupted(index)) {
/* It is possible we force to load a corrupted
clustered index if srv_load_corrupted is set.
Mark the table as corrupted in this case */
table->corrupted = TRUE;
}
}
#if 0
@ -1867,6 +1941,7 @@ err_exit:
mutex_exit(&dict_foreign_err_mutex);
}
#endif /* 0 */
func_exit:
mem_heap_free(heap);
return(table);

View File

@ -1043,6 +1043,8 @@ convert_error_code_to_mysql(
#endif /* HA_ERR_TOO_MANY_CONCURRENT_TRXS */
case DB_UNSUPPORTED:
return(HA_ERR_UNSUPPORTED);
case DB_INDEX_CORRUPT:
return(HA_ERR_INDEX_CORRUPT);
}
}
@ -2078,6 +2080,29 @@ no_db_name:
}
/*****************************************************************//**
A wrapper function of innobase_convert_name(), convert a table or
index name to the MySQL system_charset_info (UTF-8) and quote it if needed.
@return pointer to the end of buf */
static inline
void
innobase_format_name(
/*==================*/
char* buf, /*!< out: buffer for converted identifier */
ulint buflen, /*!< in: length of buf, in bytes */
const char* name, /*!< in: index or table name to format */
ibool is_index_name) /*!< in: index name */
{
const char* bufend;
bufend = innobase_convert_name(buf, buflen, name, strlen(name),
NULL, !is_index_name);
ut_ad((ulint) (bufend - buf) < buflen);
buf[bufend - buf] = '\0';
}
/**********************************************************************//**
Determines if the currently running transaction has been interrupted.
@return TRUE if interrupted */
@ -5664,12 +5689,14 @@ ha_innobase::index_read(
index = prebuilt->index;
if (UNIV_UNLIKELY(index == NULL)) {
if (UNIV_UNLIKELY(index == NULL) || dict_index_is_corrupted(index)) {
prebuilt->index_usable = FALSE;
DBUG_RETURN(HA_ERR_CRASHED);
}
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
DBUG_RETURN(HA_ERR_TABLE_DEF_CHANGED);
DBUG_RETURN(dict_index_is_corrupted(index)
? HA_ERR_INDEX_CORRUPT
: HA_ERR_TABLE_DEF_CHANGED);
}
/* Note that if the index for which the search template is built is not
@ -5855,10 +5882,33 @@ ha_innobase::change_active_index(
prebuilt->index);
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
push_warning_printf(user_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
HA_ERR_TABLE_DEF_CHANGED,
"InnoDB: insufficient history for index %u",
keynr);
if (dict_index_is_corrupted(prebuilt->index)) {
char index_name[MAX_FULL_NAME_LEN + 1];
char table_name[MAX_FULL_NAME_LEN + 1];
innobase_format_name(
index_name, sizeof index_name,
prebuilt->index->name, TRUE);
innobase_format_name(
table_name, sizeof table_name,
prebuilt->index->table->name, FALSE);
push_warning_printf(
user_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
HA_ERR_INDEX_CORRUPT,
"InnoDB: Index %s for table %s is"
" marked as corrupted",
index_name, table_name);
DBUG_RETURN(1);
} else {
push_warning_printf(
user_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
HA_ERR_TABLE_DEF_CHANGED,
"InnoDB: insufficient history for index %u",
keynr);
}
/* The caller seems to ignore this. Thus, we must check
this again in row_search_for_mysql(). */
DBUG_RETURN(2);
@ -7518,6 +7568,10 @@ ha_innobase::records_in_range(
n_rows = HA_POS_ERROR;
goto func_exit;
}
if (dict_index_is_corrupted(index)) {
n_rows = HA_ERR_INDEX_CORRUPT;
goto func_exit;
}
if (UNIV_UNLIKELY(!row_merge_is_index_usable(prebuilt->trx, index))) {
n_rows = HA_ERR_TABLE_DEF_CHANGED;
goto func_exit;
@ -8184,6 +8238,7 @@ ha_innobase::check(
ulint n_rows_in_table = ULINT_UNDEFINED;
ibool is_ok = TRUE;
ulint old_isolation_level;
ibool table_corrupted;
DBUG_ENTER("ha_innobase::check");
DBUG_ASSERT(thd == ha_thd());
@ -8225,6 +8280,14 @@ ha_innobase::check(
prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
/* Check whether the table is already marked as corrupted
before running the check table */
table_corrupted = prebuilt->table->corrupted;
/* Reset table->corrupted bit so that check table can proceed to
do additional check */
prebuilt->table->corrupted = FALSE;
/* Enlarge the fatal lock wait timeout during CHECK TABLE. */
mutex_enter(&kernel_mutex);
srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
@ -8233,6 +8296,7 @@ ha_innobase::check(
for (index = dict_table_get_first_index(prebuilt->table);
index != NULL;
index = dict_table_get_next_index(index)) {
char index_name[MAX_FULL_NAME_LEN + 1];
#if 0
fputs("Validating index ", stderr);
ut_print_name(stderr, trx, FALSE, index->name);
@ -8241,11 +8305,16 @@ ha_innobase::check(
if (!btr_validate_index(index, prebuilt->trx)) {
is_ok = FALSE;
innobase_format_name(
index_name, sizeof index_name,
prebuilt->index->name, TRUE);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_NOT_KEYFILE,
"InnoDB: The B-tree of"
" index '%-.200s' is corrupted.",
index->name);
" index %s is corrupted.",
index_name);
continue;
}
@ -8258,11 +8327,26 @@ ha_innobase::check(
prebuilt->trx, prebuilt->index);
if (UNIV_UNLIKELY(!prebuilt->index_usable)) {
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
HA_ERR_TABLE_DEF_CHANGED,
"InnoDB: Insufficient history for"
" index '%-.200s'",
index->name);
innobase_format_name(
index_name, sizeof index_name,
prebuilt->index->name, TRUE);
if (dict_index_is_corrupted(prebuilt->index)) {
push_warning_printf(
user_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
HA_ERR_INDEX_CORRUPT,
"InnoDB: Index %s is marked as"
" corrupted",
index_name);
is_ok = FALSE;
} else {
push_warning_printf(
thd, MYSQL_ERROR::WARN_LEVEL_WARN,
HA_ERR_TABLE_DEF_CHANGED,
"InnoDB: Insufficient history for"
" index %s",
index_name);
}
continue;
}
@ -8276,12 +8360,19 @@ ha_innobase::check(
prebuilt->select_lock_type = LOCK_NONE;
if (!row_check_index_for_mysql(prebuilt, index, &n_rows)) {
innobase_format_name(
index_name, sizeof index_name,
index->name, TRUE);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_NOT_KEYFILE,
"InnoDB: The B-tree of"
" index '%-.200s' is corrupted.",
index->name);
" index %s is corrupted.",
index_name);
is_ok = FALSE;
row_mysql_lock_data_dictionary(prebuilt->trx);
dict_set_corrupted(index);
row_mysql_unlock_data_dictionary(prebuilt->trx);
}
if (thd_killed(user_thd)) {
@ -8308,6 +8399,20 @@ ha_innobase::check(
}
}
if (table_corrupted) {
/* If some previous operation has marked the table as
corrupted in memory, and has not propagated such to
clustered index, we will do so here */
index = dict_table_get_first_index(prebuilt->table);
if (!dict_index_is_corrupted(index)) {
mutex_enter(&dict_sys->mutex);
dict_set_corrupted(index);
mutex_exit(&dict_sys->mutex);
}
prebuilt->table->corrupted = TRUE;
}
/* Restore the original isolation level */
prebuilt->trx->isolation_level = old_isolation_level;
@ -11101,6 +11206,11 @@ static MYSQL_SYSVAR_BOOL(large_prefix, innobase_large_prefix,
"Support large index prefix length of REC_VERSION_56_MAX_INDEX_COL_LEN (3072) bytes.",
NULL, NULL, FALSE);
static MYSQL_SYSVAR_BOOL(force_load_corrupted, srv_load_corrupted,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Force InnoDB to load metadata of corrupted table.",
NULL, NULL, FALSE);
static MYSQL_SYSVAR_BOOL(locks_unsafe_for_binlog, innobase_locks_unsafe_for_binlog,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Force InnoDB to not use next-key locking, to use only row-level locking.",
@ -11360,6 +11470,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(flush_method),
MYSQL_SYSVAR(force_recovery),
MYSQL_SYSVAR(large_prefix),
MYSQL_SYSVAR(force_load_corrupted),
MYSQL_SYSVAR(locks_unsafe_for_binlog),
MYSQL_SYSVAR(lock_wait_timeout),
#ifdef UNIV_LOG_ARCHIVE

View File

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
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
@ -402,7 +402,7 @@ ibuf_tree_root_get(
block = buf_page_get(
IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
root = buf_block_get_frame(block);
@ -549,7 +549,7 @@ ibuf_init_at_db_start(void)
block = buf_page_get(
IBUF_SPACE_ID, 0, FSP_IBUF_TREE_ROOT_PAGE_NO,
RW_X_LATCH, &mtr);
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
root = buf_block_get_frame(block);
}
@ -2209,7 +2209,8 @@ ibuf_add_free_page(void)
} else {
buf_block_t* block = buf_page_get(
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
page = buf_block_get_frame(block);
}
@ -2332,8 +2333,7 @@ ibuf_remove_free_page(void)
block = buf_page_get(
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
page = buf_block_get_frame(block);
}
@ -3022,7 +3022,7 @@ ibuf_get_volume_buffered(
IBUF_SPACE_ID, 0, prev_page_no, RW_X_LATCH,
mtr);
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
prev_page = buf_block_get_frame(block);
@ -3095,7 +3095,7 @@ count_later:
IBUF_SPACE_ID, 0, next_page_no, RW_X_LATCH,
mtr);
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
next_page = buf_block_get_frame(block);
@ -3333,7 +3333,7 @@ ibuf_set_entry_counter(
IBUF_SPACE_ID, 0, prev_page_no,
RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
prev_page = buf_block_get_frame(block);
@ -4419,6 +4419,7 @@ ibuf_merge_or_delete_for_page(
ut_ad(!block || buf_block_get_space(block) == space);
ut_ad(!block || buf_block_get_page_no(block) == page_no);
ut_ad(!block || buf_block_get_zip_size(block) == zip_size);
ut_ad(!block || buf_block_get_io_fix(block) == BUF_IO_READ);
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE
|| trx_sys_hdr_page(space, page_no)) {
@ -4571,7 +4572,13 @@ loop:
ut_a(success);
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
/* This is a user page (secondary index leaf page),
but we pretend that it is a change buffer page in
order to obey the latching order. This should be OK,
because buffered changes are applied immediately while
the block is io-fixed. Other threads must not try to
latch an io-fixed block. */
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
}
/* Position pcur in the insert buffer at the first entry for this
@ -4675,7 +4682,12 @@ loop:
__FILE__, __LINE__, &mtr);
ut_a(success);
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
/* This is a user page (secondary
index leaf page), but it should be OK
to use too low latching order for it,
as the block is io-fixed. */
buf_block_dbg_add_level(
block, SYNC_IBUF_TREE_NODE);
if (!ibuf_restore_pos(space, page_no,
search_tuple,

View File

@ -199,26 +199,45 @@ btr_block_get_func(
ulint mode, /*!< in: latch mode */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in/out: mtr */
__attribute__((nonnull));
# ifdef UNIV_SYNC_DEBUG
const dict_index_t* index, /*!< in: index tree, may be NULL
if it is not an insert buffer tree */
# endif /* UNIV_SYNC_DEBUG */
mtr_t* mtr); /*!< in/out: mini-transaction */
# ifdef UNIV_SYNC_DEBUG
/** Gets a buffer page and declares its latching order level.
@param space tablespace identifier
@param zip_size compressed page size in bytes or 0 for uncompressed pages
@param page_no page number
@param mode latch mode
@param index index tree, may be NULL if not the insert buffer tree
@param mtr mini-transaction handle
@return the block descriptor */
# define btr_block_get(space,zip_size,page_no,mode,mtr) \
btr_block_get_func(space,zip_size,page_no,mode,__FILE__,__LINE__,mtr)
# define btr_block_get(space,zip_size,page_no,mode,index,mtr) \
btr_block_get_func(space,zip_size,page_no,mode, \
__FILE__,__LINE__,index,mtr)
# else /* UNIV_SYNC_DEBUG */
/** Gets a buffer page and declares its latching order level.
@param space tablespace identifier
@param zip_size compressed page size in bytes or 0 for uncompressed pages
@param page_no page number
@param mode latch mode
@param idx index tree, may be NULL if not the insert buffer tree
@param mtr mini-transaction handle
@return the block descriptor */
# define btr_block_get(space,zip_size,page_no,mode,idx,mtr) \
btr_block_get_func(space,zip_size,page_no,mode,__FILE__,__LINE__,mtr)
# endif /* UNIV_SYNC_DEBUG */
/** Gets a buffer page and declares its latching order level.
@param space tablespace identifier
@param zip_size compressed page size in bytes or 0 for uncompressed pages
@param page_no page number
@param mode latch mode
@param idx index tree, may be NULL if not the insert buffer tree
@param mtr mini-transaction handle
@return the uncompressed page frame */
# define btr_page_get(space,zip_size,page_no,mode,mtr) \
buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,mtr))
# define btr_page_get(space,zip_size,page_no,mode,idx,mtr) \
buf_block_get_frame(btr_block_get(space,zip_size,page_no,mode,idx,mtr))
#endif /* !UNIV_HOTBACKUP */
/**************************************************************//**
Gets the index id field of a page.
@ -344,8 +363,7 @@ btr_free_root(
ulint zip_size, /*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint root_page_no, /*!< in: root page number */
mtr_t* mtr); /*!< in: a mini-transaction which has already
been started */
mtr_t* mtr); /*!< in/out: mini-transaction */
/*************************************************************//**
Makes tree one level higher by splitting the root, and inserts
the tuple. It is assumed that mtr contains an x-latch on the tree.

View File

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
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
@ -48,6 +48,10 @@ btr_block_get_func(
ulint mode, /*!< in: latch mode */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
#ifdef UNIV_SYNC_DEBUG
const dict_index_t* index, /*!< in: index tree, may be NULL
if it is not an insert buffer tree */
#endif /* UNIV_SYNC_DEBUG */
mtr_t* mtr) /*!< in/out: mtr */
{
buf_block_t* block;
@ -57,7 +61,9 @@ btr_block_get_func(
if (mode != RW_NO_LATCH) {
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
buf_block_dbg_add_level(
block, index != NULL && dict_index_is_ibuf(index)
? SYNC_IBUF_TREE_NODE : SYNC_TREE_NODE);
}
return(block);

View File

@ -203,6 +203,17 @@ void
buf_LRU_stat_update(void);
/*=====================*/
/******************************************************************//**
Remove one page from LRU list and put it to free list */
UNIV_INTERN
void
buf_LRU_free_one_page(
/*==================*/
buf_page_t* bpage) /*!< in/out: block, must contain a file page and
be in a state where it can be freed; there
may or may not be a hash index to the page */
__attribute__((nonnull));
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/**********************************************************************//**
Validates the LRU list.

View File

@ -110,6 +110,7 @@ enum db_err {
foreign keys as its prefix columns */
DB_TOO_BIG_INDEX_COL, /* index column size exceeds maximum
limit */
DB_INDEX_CORRUPT, /* we have corrupted index */
/* The following are partial failure codes */
DB_FAIL = 1000,

View File

@ -137,8 +137,10 @@ dict_create(void);
header is created */
/*-------------------------------------------------------------*/
/* The field number of the page number field in the sys_indexes table
clustered index */
/* The field numbers in the SYS_TABLES clustered index */
#define DICT_SYS_TABLES_TYPE_FIELD 5
/* The field numbers in the SYS_INDEXES clustered index */
#define DICT_SYS_INDEXES_PAGE_NO_FIELD 8
#define DICT_SYS_INDEXES_SPACE_NO_FIELD 7
#define DICT_SYS_INDEXES_TYPE_FIELD 6

View File

@ -585,6 +585,20 @@ dict_table_get_next_index(
# define dict_table_get_next_index(index) UT_LIST_GET_NEXT(indexes, index)
#endif /* UNIV_DEBUG */
#endif /* !UNIV_HOTBACKUP */
/* Skip corrupted index */
#define dict_table_skip_corrupt_index(index) \
while (index && dict_index_is_corrupted(index)) { \
index = dict_table_get_next_index(index); \
}
/* Get the next non-corrupt index */
#define dict_table_next_uncorrupted_index(index) \
do { \
index = dict_table_get_next_index(index); \
dict_table_skip_corrupt_index(index); \
} while (0)
/********************************************************************//**
Check whether the index is the clustered index.
@return nonzero for clustered index, zero for other indexes */
@ -593,7 +607,7 @@ ulint
dict_index_is_clust(
/*================*/
const dict_index_t* index) /*!< in: index */
__attribute__((pure));
__attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Check whether the index is unique.
@return nonzero for unique index, zero for other indexes */
@ -602,7 +616,7 @@ ulint
dict_index_is_unique(
/*=================*/
const dict_index_t* index) /*!< in: index */
__attribute__((pure));
__attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Check whether the index is the insert buffer tree.
@return nonzero for insert buffer, zero for other indexes */
@ -611,7 +625,7 @@ ulint
dict_index_is_ibuf(
/*===============*/
const dict_index_t* index) /*!< in: index */
__attribute__((pure));
__attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Check whether the index is a secondary index or the insert buffer tree.
@return nonzero for insert buffer, zero for other indexes */
@ -620,7 +634,7 @@ ulint
dict_index_is_sec_or_ibuf(
/*======================*/
const dict_index_t* index) /*!< in: index */
__attribute__((pure));
__attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Gets the number of user-defined columns in a table in the dictionary
@ -630,7 +644,8 @@ UNIV_INLINE
ulint
dict_table_get_n_user_cols(
/*=======================*/
const dict_table_t* table); /*!< in: table */
const dict_table_t* table) /*!< in: table */
__attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Gets the number of system columns in a table in the dictionary cache.
@return number of system (e.g., ROW_ID) columns of a table */
@ -638,7 +653,8 @@ UNIV_INLINE
ulint
dict_table_get_n_sys_cols(
/*======================*/
const dict_table_t* table); /*!< in: table */
const dict_table_t* table) /*!< in: table */
__attribute__((nonnull, pure, warn_unused_result));
/********************************************************************//**
Gets the number of all columns (also system) in a table in the dictionary
cache.
@ -647,7 +663,8 @@ UNIV_INLINE
ulint
dict_table_get_n_cols(
/*==================*/
const dict_table_t* table); /*!< in: table */
const dict_table_t* table) /*!< in: table */
__attribute__((nonnull, pure, warn_unused_result));
#ifdef UNIV_DEBUG
/********************************************************************//**
Gets the nth column of a table.
@ -1243,6 +1260,56 @@ void
dict_close(void);
/*============*/
/**********************************************************************//**
Check whether the table is corrupted.
@return nonzero for corrupted table, zero for valid tables */
UNIV_INLINE
ulint
dict_table_is_corrupted(
/*====================*/
const dict_table_t* table) /*!< in: table */
__attribute__((nonnull, pure, warn_unused_result));
/**********************************************************************//**
Check whether the index is corrupted.
@return nonzero for corrupted index, zero for valid indexes */
UNIV_INLINE
ulint
dict_index_is_corrupted(
/*====================*/
const dict_index_t* index) /*!< in: index */
__attribute__((nonnull, pure, warn_unused_result));
/**********************************************************************//**
Flags an index and table corrupted both in the data dictionary cache
and in the system table SYS_INDEXES. */
UNIV_INTERN
void
dict_set_corrupted(
/*===============*/
dict_index_t* index) /*!< in/out: index */
UNIV_COLD __attribute__((nonnull));
/**********************************************************************//**
Flags an index corrupted in the data dictionary cache only. This
is used mostly to mark a corrupted index when index's own dictionary
is corrupted, and we force to load such index for repair purpose */
UNIV_INTERN
void
dict_set_corrupted_index_cache_only(
/*================================*/
dict_index_t* index); /*!< in/out: index */
/**********************************************************************//**
Flags a table with specified space_id corrupted in the table dictionary
cache.
@return TRUE if successful */
UNIV_INTERN
ibool
dict_set_corrupted_by_space(
/*========================*/
ulint space_id); /*!< in: space ID */
#ifndef UNIV_NONINL
#include "dict0dict.ic"
#endif

View File

@ -27,6 +27,7 @@ Created 1/8/1996 Heikki Tuuri
#ifndef UNIV_HOTBACKUP
#include "dict0load.h"
#include "rem0types.h"
#include "srv0srv.h"
/*********************************************************************//**
Gets the minimum number of bytes per character.
@ -828,7 +829,7 @@ dict_table_check_if_in_cache_low(
}
/**********************************************************************//**
load a table into dictionary cache, ignore any error specified during load;
load a table into dictionary cache, ignore any error specified during load;
@return table, NULL if not found */
UNIV_INLINE
dict_table_t*
@ -872,6 +873,18 @@ dict_table_get_low(
table = dict_table_check_if_in_cache_low(table_name);
if (table && table->corrupted) {
fprintf(stderr, "InnoDB: table");
ut_print_name(stderr, NULL, TRUE, table->name);
if (srv_load_corrupted) {
fputs(" is corrupted, but"
" innodb_force_load_corrupted is set\n", stderr);
} else {
fputs(" is corrupted\n", stderr);
return(NULL);
}
}
if (table == NULL) {
table = dict_load_table(table_name, TRUE, DICT_ERR_IGNORE_NONE);
}
@ -937,4 +950,35 @@ dict_max_field_len_store_undo(
return(prefix_len);
}
/********************************************************************//**
Check whether the table is corrupted.
@return nonzero for corrupted table, zero for valid tables */
UNIV_INLINE
ulint
dict_table_is_corrupted(
/*====================*/
const dict_table_t* table) /*!< in: table */
{
ut_ad(table);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
return(UNIV_UNLIKELY(table->corrupted));
}
/********************************************************************//**
Check whether the index is corrupted.
@return nonzero for corrupted index, zero for valid indexes */
UNIV_INLINE
ulint
dict_index_is_corrupted(
/*====================*/
const dict_index_t* index) /*!< in: index */
{
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
return(UNIV_UNLIKELY((index->type & DICT_CORRUPT)
|| (index->table && index->table->corrupted)));
}
#endif /* !UNIV_HOTBACKUP */

View File

@ -51,7 +51,12 @@ combination of types */
#define DICT_UNIQUE 2 /*!< unique index */
#define DICT_UNIVERSAL 4 /*!< index which can contain records from any
other index */
#define DICT_IBUF 8 /*!< insert buffer tree */
#define DICT_IBUF 8 /*!< insert buffer tree */
#define DICT_CORRUPT 16 /*!< bit to store the corrupted flag
in SYS_INDEXES.TYPE */
#define DICT_IT_BITS 5 /*!< number of bits used for
SYS_INDEXES.TYPE */
/* @} */
/** Types for a table object */
@ -369,8 +374,9 @@ struct dict_index_struct{
/*!< space where the index tree is placed */
unsigned page:32;/*!< index tree root page number */
#endif /* !UNIV_HOTBACKUP */
unsigned type:4; /*!< index type (DICT_CLUSTERED, DICT_UNIQUE,
DICT_UNIVERSAL, DICT_IBUF) */
unsigned type:DICT_IT_BITS;
/*!< index type (DICT_CLUSTERED, DICT_UNIQUE,
DICT_UNIVERSAL, DICT_IBUF, DICT_CORRUPT) */
unsigned trx_id_offset:10;/*!< position of the trx id column
in a clustered index record, if the fields
before it are known to be of a fixed size,
@ -391,8 +397,6 @@ struct dict_index_struct{
/*!< TRUE if this index is marked to be
dropped in ha_innobase::prepare_drop_index(),
otherwise FALSE */
unsigned corrupted:1;
/*!< TRUE if the index object is corrupted */
dict_field_t* fields; /*!< array of field descriptions */
#ifndef UNIV_HOTBACKUP
UT_LIST_NODE_T(dict_index_t)

View File

@ -51,7 +51,8 @@ be or-ed together */
enum dict_err_ignore {
DICT_ERR_IGNORE_NONE = 0, /*!< no error to ignore */
DICT_ERR_IGNORE_INDEX_ROOT = 1, /*!< ignore error if index root
page is FIL_NUL or incorrect value */
page is FIL_NULL or incorrect value */
DICT_ERR_IGNORE_CORRUPT = 2, /*!< skip corrupted indexes */
DICT_ERR_IGNORE_ALL = 0xFFFF /*!< ignore all errors */
};

View File

@ -141,6 +141,10 @@ extern ulint srv_log_buffer_size;
extern ulong srv_flush_log_at_trx_commit;
extern char srv_adaptive_flushing;
/* If this flag is TRUE, then we will load the indexes' (and tables') metadata
even if they are marked as "corrupted". Mostly it is for DBA to process
corrupted index and table */
extern my_bool srv_load_corrupted;
/* The sort order table of the MySQL latin1_swedish_ci character set
collation */

View File

@ -638,10 +638,6 @@ or row lock! */
#define SYNC_DICT_HEADER 995
#define SYNC_IBUF_HEADER 914
#define SYNC_IBUF_PESS_INSERT_MUTEX 912
#define SYNC_IBUF_MUTEX 910 /* ibuf mutex is really below
SYNC_FSP_PAGE: we assign a value this
high only to make the program to pass
the debug checks */
/*-------------------------------*/
#define SYNC_INDEX_TREE 900
#define SYNC_TREE_NODE_NEW 892
@ -657,8 +653,11 @@ or row lock! */
#define SYNC_FSP 400
#define SYNC_FSP_PAGE 395
/*------------------------------------- Insert buffer headers */
/*------------------------------------- ibuf_mutex */
#define SYNC_IBUF_MUTEX 370 /* ibuf_mutex */
/*------------------------------------- Insert buffer tree */
#define SYNC_IBUF_INDEX_TREE 360
#define SYNC_IBUF_TREE_NODE_NEW 359
#define SYNC_IBUF_TREE_NODE 358
#define SYNC_IBUF_BITMAP_MUTEX 351
#define SYNC_IBUF_BITMAP 350
/*------------------------------------- MySQL query cache mutex */

View File

@ -568,7 +568,7 @@ opt_search_plan_for_table(
best_last_op = last_op;
}
index = dict_table_get_next_index(index);
dict_table_next_uncorrupted_index(index);
}
plan->index = best_index;

View File

@ -118,6 +118,9 @@ ins_node_create_entry_list(
node->entry_sys_heap);
UT_LIST_ADD_LAST(tuple_list, node->entry_list, entry);
/* We will include all indexes (include those corrupted
secondary indexes) in the entry list. Filteration of
these corrupted index will be done in row_ins() */
index = dict_table_get_next_index(index);
}
}
@ -2046,7 +2049,6 @@ row_ins_index_entry_low(
mtr_start(&mtr);
if (err != DB_SUCCESS) {
goto function_exit;
}
@ -2431,6 +2433,13 @@ row_ins(
node->index = dict_table_get_next_index(node->index);
node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry);
/* Skip corrupted secondar index and its entry */
while (node->index && dict_index_is_corrupted(node->index)) {
node->index = dict_table_get_next_index(node->index);
node->entry = UT_LIST_GET_NEXT(tuple_list, node->entry);
}
}
ut_ad(node->entry == NULL);

View File

@ -2554,8 +2554,9 @@ row_merge_is_index_usable(
const trx_t* trx, /*!< in: transaction */
const dict_index_t* index) /*!< in: index to check */
{
return(!trx->read_view
|| read_view_sees_trx_id(trx->read_view, index->trx_id));
return(!dict_index_is_corrupted(index)
&& (!trx->read_view
|| read_view_sees_trx_id(trx->read_view, index->trx_id)));
}
/*********************************************************************//**

View File

@ -3098,7 +3098,8 @@ row_drop_table_for_mysql(
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
table = dict_table_get_low_ignore_err(name, DICT_ERR_IGNORE_INDEX_ROOT);
table = dict_table_get_low_ignore_err(
name, DICT_ERR_IGNORE_INDEX_ROOT | DICT_ERR_IGNORE_CORRUPT);
if (!table) {
err = DB_TABLE_NOT_FOUND;

View File

@ -469,6 +469,13 @@ row_purge_del_mark(
heap = mem_heap_create(1024);
while (node->index != NULL) {
/* skip corrupted secondary index */
dict_table_skip_corrupt_index(node->index);
if (!node->index) {
break;
}
index = node->index;
/* Build the index entry */
@ -516,6 +523,12 @@ row_purge_upd_exist_or_extern_func(
heap = mem_heap_create(1024);
while (node->index != NULL) {
dict_table_skip_corrupt_index(node->index);
if (!node->index) {
break;
}
index = node->index;
if (row_upd_changes_ord_field_binary(node->index, node->update,

View File

@ -3441,6 +3441,13 @@ row_search_for_mysql(
return(DB_MISSING_HISTORY);
}
if (dict_index_is_corrupted(index)) {
#ifdef UNIV_SYNC_DEBUG
ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
#endif /* UNIV_SYNC_DEBUG */
return(DB_CORRUPTION);
}
if (UNIV_UNLIKELY(prebuilt->magic_n != ROW_PREBUILT_ALLOCATED)) {
fprintf(stderr,
"InnoDB: Error: trying to free a corrupt\n"

View File

@ -328,6 +328,8 @@ row_undo_ins(
node->index = dict_table_get_next_index(
dict_table_get_first_index(node->table));
dict_table_skip_corrupt_index(node->index);
while (node->index != NULL) {
dtuple_t* entry;
ulint err;
@ -355,7 +357,7 @@ row_undo_ins(
}
}
node->index = dict_table_get_next_index(node->index);
dict_table_next_uncorrupted_index(node->index);
}
log_free_check();

View File

@ -573,6 +573,14 @@ row_undo_mod_upd_del_sec(
heap = mem_heap_create(1024);
while (node->index != NULL) {
/* Skip all corrupted secondary index */
dict_table_skip_corrupt_index(node->index);
if (!node->index) {
break;
}
index = node->index;
entry = row_build_index_entry(node->row, node->ext,
@ -626,6 +634,13 @@ row_undo_mod_del_mark_sec(
heap = mem_heap_create(1024);
while (node->index != NULL) {
/* Skip all corrupted secondary index */
dict_table_skip_corrupt_index(node->index);
if (!node->index) {
break;
}
index = node->index;
entry = row_build_index_entry(node->row, node->ext,
@ -677,6 +692,13 @@ row_undo_mod_upd_exist_sec(
heap = mem_heap_create(1024);
while (node->index != NULL) {
/* Skip all corrupted secondary index */
dict_table_skip_corrupt_index(node->index);
if (!node->index) {
break;
}
index = node->index;
if (row_upd_changes_ord_field_binary(node->index, node->update,
@ -859,6 +881,9 @@ row_undo_mod(
node->index = dict_table_get_next_index(
dict_table_get_first_index(node->table));
/* Skip all corrupted secondary index */
dict_table_skip_corrupt_index(node->index);
if (node->rec_type == TRX_UNDO_UPD_EXIST_REC) {
err = row_undo_mod_upd_exist_sec(node, thr);

View File

@ -2320,6 +2320,13 @@ row_upd(
while (node->index != NULL) {
/* Skip corrupted index */
dict_table_skip_corrupt_index(node->index);
if (!node->index) {
break;
}
log_free_check();
err = row_upd_sec_step(node, thr);

View File

@ -1232,6 +1232,7 @@ sync_thread_add_level(
case SYNC_DICT_HEADER:
case SYNC_TRX_I_S_RWLOCK:
case SYNC_TRX_I_S_LAST_READ:
case SYNC_IBUF_MUTEX:
if (!sync_thread_levels_g(array, level, TRUE)) {
fprintf(stderr,
"InnoDB: sync_thread_levels_g(array, %lu)"
@ -1317,21 +1318,27 @@ sync_thread_add_level(
|| sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE));
break;
case SYNC_TREE_NODE_NEW:
ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE)
|| sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE));
break;
case SYNC_INDEX_TREE:
if (sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
&& sync_thread_levels_contain(array, SYNC_FSP)) {
ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1,
TRUE));
} else {
ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1,
TRUE));
}
ut_a(sync_thread_levels_g(array, SYNC_TREE_NODE - 1, TRUE));
break;
case SYNC_IBUF_MUTEX:
ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1, TRUE));
case SYNC_IBUF_TREE_NODE:
ut_a(sync_thread_levels_contain(array, SYNC_IBUF_INDEX_TREE)
|| sync_thread_levels_g(array, SYNC_IBUF_TREE_NODE - 1,
TRUE));
break;
case SYNC_IBUF_TREE_NODE_NEW:
ut_a(sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
break;
case SYNC_IBUF_INDEX_TREE:
if (sync_thread_levels_contain(array, SYNC_FSP)) {
ut_a(sync_thread_levels_g(
array, SYNC_FSP_PAGE - 1, TRUE));
} else {
ut_a(sync_thread_levels_g(
array, SYNC_IBUF_TREE_NODE - 1, TRUE));
}
break;
case SYNC_IBUF_PESS_INSERT_MUTEX:
ut_a(sync_thread_levels_g(array, SYNC_FSP - 1, TRUE));

View File

@ -712,6 +712,8 @@ ut_strerr(
return("No index on referencing keys in referencing table");
case DB_PARENT_NO_INDEX:
return("No index on referenced keys in referenced table");
case DB_INDEX_CORRUPT:
return("Index corrupted");
case DB_END_OF_INDEX:
return("End of index");
/* do not add default: in order to produce a warning if new code

View File

@ -421,7 +421,7 @@ mkdir debug
# XXX: install_layout so we can't just set it based on INSTALL_LAYOUT=RPM
${CMAKE} ../%{src_dir} -DBUILD_CONFIG=mysql_release -DINSTALL_LAYOUT=RPM \
-DCMAKE_BUILD_TYPE=Debug \
-DMYSQL_UNIX_ADDR="/var/lib/mysql/mysql.sock" \
-DMYSQL_UNIX_ADDR="%{mysqldatadir}/mysql.sock" \
-DFEATURE_SET="%{feature_set}" \
-DCOMPILATION_COMMENT="%{compilation_comment_debug}" \
-DMYSQL_SERVER_SUFFIX="%{server_suffix}"
@ -436,7 +436,7 @@ mkdir release
# XXX: install_layout so we can't just set it based on INSTALL_LAYOUT=RPM
${CMAKE} ../%{src_dir} -DBUILD_CONFIG=mysql_release -DINSTALL_LAYOUT=RPM \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DMYSQL_UNIX_ADDR="/var/lib/mysql/mysql.sock" \
-DMYSQL_UNIX_ADDR="%{mysqldatadir}/mysql.sock" \
-DFEATURE_SET="%{feature_set}" \
-DCOMPILATION_COMMENT="%{compilation_comment_release}" \
-DMYSQL_SERVER_SUFFIX="%{server_suffix}"
@ -1133,6 +1133,11 @@ echo "=====" >> $STATUS_HISTORY
# merging BK trees)
##############################################################################
%changelog
* Fri Aug 19 2011 Joerg Bruehe <joerg.bruehe@oracle.com>
- Null-upmerge the fix of bug#37165: This spec file is not affected.
- Replace "/var/lib/mysql" by the spec file variable "%{mysqldatadir}".
* Mon Jul 25 2011 Chuck Bell <chuck.bell@oracle.com>
- Added the mysql_plugin client - enables or disables plugins.