mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
MDEV-33277 In-place upgrade causes invalid AUTO_INCREMENT values
MDEV-33308 CHECK TABLE is modifying .frm file even if --read-only As noted in commitd0ef1aaf61
, MySQL as well as older versions of MariaDB server would during ALTER TABLE ... IMPORT TABLESPACE write bogus values to the PAGE_MAX_TRX_ID field to pages of the clustered index, instead of letting that field remain 0. In commit8777458a6e
this field was repurposed for PAGE_ROOT_AUTO_INC in the clustered index root page. To avoid trouble when upgrading from MySQL or older versions of MariaDB, we will try to detect and correct bogus values of PAGE_ROOT_AUTO_INC when opening a table for the first time from the SQL layer. btr_read_autoinc_with_fallback(): Add the parameters to mysql_version,max to indicate the TABLE_SHARE::mysql_version of the .frm file and the maximum value allowed for the type of the AUTO_INCREMENT column. In case the table was originally created in MySQL or an older version of MariaDB, read also the maximum value of the AUTO_INCREMENT column from the table and reset the PAGE_ROOT_AUTO_INC if it is above the limit. dict_table_t::get_index(const dict_col_t &) const: Find an index that starts with the specified column. ha_innobase::check_for_upgrade(): Return HA_ADMIN_FAILED if InnoDB needs upgrading but is in read-only mode. In this way, the call to update_frm_version() will be skipped. row_import_autoinc(): Adjust the AUTO_INCREMENT column at the end of ALTER TABLE...IMPORT TABLESPACE. This refinement was suggested by Debarun Banerjee. The changes outside InnoDB were developed by Michael 'Monty' Widenius: Added print_check_msg() service for easy reporting of check/repair messages in ENGINE=Aria and ENGINE=InnoDB. Fixed that CHECK TABLE do not update the .frm file under --read-only. Added 'handler_flags' to HA_CHECK_OPT as a way for storage engines to store state from handler::check_for_upgrade(). Reviewed by: Debarun Banerjee
This commit is contained in:
parent
915d951431
commit
0381921e26
20 changed files with 723 additions and 144 deletions
44
include/mysql/service_print_check_msg.h
Normal file
44
include/mysql/service_print_check_msg.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* Copyright (c) 2019, MariaDB Corporation.
|
||||
|
||||
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 Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
@file include/mysql/service_print_check_msg.h
|
||||
This service provides functions to write messages for check or repair
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
extern struct print_check_msg_service_st {
|
||||
void (*print_check_msg)(MYSQL_THD, const char *db_name, const char *table_name,
|
||||
const char *op, const char *msg_type, const char *message,
|
||||
my_bool print_to_log);
|
||||
} *print_check_msg_service;
|
||||
|
||||
#ifdef MYSQL_DYNAMIC_PLUGIN
|
||||
# define print_check_msg_context(_THD) print_check_msg_service->print_check_msg
|
||||
#else
|
||||
extern void print_check_msg(MYSQL_THD, const char *db_name, const char *table_name,
|
||||
const char *op, const char *msg_type, const char *message,
|
||||
my_bool print_to_log);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -45,3 +45,4 @@
|
|||
#define VERSION_json 0x0100
|
||||
#define VERSION_sql_service 0x0100
|
||||
#define VERSION_thd_mdl 0x0100
|
||||
#define VERSION_print_check_msg 0x0100
|
||||
|
|
|
@ -25,6 +25,7 @@ SET(MYSQLSERVICES_SOURCES
|
|||
my_crypt_service.c
|
||||
my_md5_service.c
|
||||
my_print_error_service.c
|
||||
print_check_msg_service.c
|
||||
my_sha1_service.c
|
||||
my_sha2_service.c
|
||||
my_snprintf_service.c
|
||||
|
|
18
libservices/print_check_msg_service.c
Normal file
18
libservices/print_check_msg_service.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* Copyright (c) 2024, MariaDB Plc
|
||||
|
||||
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 Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <service_versions.h>
|
||||
SERVICE_VERSION print_check_msg_context= (void*) VERSION_print_check_msg;
|
BIN
mysql-test/std_data/autoinc_import_101.frm
Normal file
BIN
mysql-test/std_data/autoinc_import_101.frm
Normal file
Binary file not shown.
BIN
mysql-test/std_data/autoinc_import_57.frm
Normal file
BIN
mysql-test/std_data/autoinc_import_57.frm
Normal file
Binary file not shown.
232
mysql-test/suite/innodb/r/autoinc_import.result
Normal file
232
mysql-test/suite/innodb/r/autoinc_import.result
Normal file
|
@ -0,0 +1,232 @@
|
|||
CREATE TABLE t1 (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(42);
|
||||
CREATE TABLE t1b LIKE t1;
|
||||
INSERT INTO t1b VALUES(3);
|
||||
CREATE TABLE t1z LIKE t1;
|
||||
CREATE TABLE t1t (id TINYINT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
|
||||
CREATE TABLE t0t LIKE t1t;
|
||||
INSERT INTO t1t VALUES(123);
|
||||
FLUSH TABLES t1,t1b,t1t FOR EXPORT;
|
||||
UNLOCK TABLES;
|
||||
CREATE TABLE t5_7 LIKE t1;
|
||||
CREATE TABLE t5_7b LIKE t1b;
|
||||
CREATE TABLE t10_1 LIKE t1;
|
||||
CREATE TABLE t10_1b LIKE t1b;
|
||||
ALTER TABLE t1 DISCARD TABLESPACE;
|
||||
ALTER TABLE t1b DISCARD TABLESPACE;
|
||||
ALTER TABLE t1z DISCARD TABLESPACE;
|
||||
ALTER TABLE t1t DISCARD TABLESPACE;
|
||||
ALTER TABLE t0t DISCARD TABLESPACE;
|
||||
ALTER TABLE t5_7 DISCARD TABLESPACE;
|
||||
ALTER TABLE t5_7b DISCARD TABLESPACE;
|
||||
ALTER TABLE t10_1 DISCARD TABLESPACE;
|
||||
ALTER TABLE t10_1b DISCARD TABLESPACE;
|
||||
FLUSH TABLES;
|
||||
ALTER TABLE t0t IMPORT TABLESPACE;
|
||||
Warnings:
|
||||
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t0t.cfg', will attempt to import without schema verification
|
||||
INSERT INTO t0t VALUES(NULL);
|
||||
SELECT * FROM t0t;
|
||||
id
|
||||
123
|
||||
124
|
||||
DROP TABLE t0t;
|
||||
ALTER TABLE t1 IMPORT TABLESPACE;
|
||||
Warnings:
|
||||
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1.cfg', will attempt to import without schema verification
|
||||
ALTER TABLE t1b IMPORT TABLESPACE;
|
||||
Warnings:
|
||||
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1b.cfg', will attempt to import without schema verification
|
||||
ALTER TABLE t1z IMPORT TABLESPACE;
|
||||
Warnings:
|
||||
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1z.cfg', will attempt to import without schema verification
|
||||
ALTER TABLE t1t IMPORT TABLESPACE;
|
||||
Warnings:
|
||||
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t1t.cfg', will attempt to import without schema verification
|
||||
ALTER TABLE t5_7 IMPORT TABLESPACE;
|
||||
Warnings:
|
||||
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t5_7.cfg', will attempt to import without schema verification
|
||||
ALTER TABLE t5_7b IMPORT TABLESPACE;
|
||||
Warnings:
|
||||
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t5_7b.cfg', will attempt to import without schema verification
|
||||
ALTER TABLE t10_1 IMPORT TABLESPACE;
|
||||
Warnings:
|
||||
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t10_1.cfg', will attempt to import without schema verification
|
||||
ALTER TABLE t10_1b IMPORT TABLESPACE;
|
||||
Warnings:
|
||||
Warning 1810 IO Read error: (2, No such file or directory) Error opening './test/t10_1b.cfg', will attempt to import without schema verification
|
||||
FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 128 to 123 on table `test`\.`t0t`/ in mysqld.1.err
|
||||
FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 0 to 42 on table `test`\.`t1z`/ in mysqld.1.err
|
||||
FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 128 to 123 on table `test`\.`t1t`/ in mysqld.1.err
|
||||
FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 3 to 42 on table `test`\.`t5_7` \(created with version 50744\)/ in mysqld.1.err
|
||||
FOUND 1 /InnoDB: Resetting PAGE_ROOT_AUTO_INC from 3 to 42 on table `test`\.`t10_1` \(created with version 100149\)/ in mysqld.1.err
|
||||
FOUND 5 /InnoDB: Resetting PAGE_ROOT_AUTO_INC/ in mysqld.1.err
|
||||
# restart: --read-only
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
test.t1b check status OK
|
||||
test.t1t check status OK
|
||||
test.t1z check status OK
|
||||
test.t5_7 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t5_7 check status OK
|
||||
test.t5_7b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t5_7b check status OK
|
||||
test.t10_1 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t10_1 check status OK
|
||||
test.t10_1b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t10_1b check status OK
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
test.t1b check status OK
|
||||
test.t1t check status OK
|
||||
test.t1z check status OK
|
||||
test.t5_7 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t5_7 check status OK
|
||||
test.t5_7b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t5_7b check status OK
|
||||
test.t10_1 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t10_1 check status OK
|
||||
test.t10_1b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t10_1b check status OK
|
||||
# restart: --innodb-read-only --read-only
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
test.t1b check status OK
|
||||
test.t1t check status OK
|
||||
test.t1z check status OK
|
||||
test.t5_7 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t5_7 check status OK
|
||||
test.t5_7b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t5_7b check status OK
|
||||
test.t10_1 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t10_1 check status OK
|
||||
test.t10_1b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t10_1b check status OK
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
test.t1b check status OK
|
||||
test.t1t check status OK
|
||||
test.t1z check status OK
|
||||
test.t5_7 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t5_7 check status OK
|
||||
test.t5_7b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t5_7b check status OK
|
||||
test.t10_1 check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t10_1 check status OK
|
||||
test.t10_1b check note Auto_increment will be checked on each open until CHECK TABLE FOR UPGRADE is executed
|
||||
test.t10_1b check status OK
|
||||
# restart: --innodb-read-only
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
test.t1b check status OK
|
||||
test.t1t check status OK
|
||||
test.t1z check status OK
|
||||
test.t5_7 check status Operation failed
|
||||
test.t5_7b check status Operation failed
|
||||
test.t10_1 check status Operation failed
|
||||
test.t10_1b check status Operation failed
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
test.t1b check status OK
|
||||
test.t1t check status OK
|
||||
test.t1z check status OK
|
||||
test.t5_7 check status Operation failed
|
||||
test.t5_7b check status Operation failed
|
||||
test.t10_1 check status Operation failed
|
||||
test.t10_1b check status Operation failed
|
||||
SELECT COUNT(*) FROM t1;
|
||||
COUNT(*)
|
||||
1
|
||||
SELECT COUNT(*) FROM t1b;
|
||||
COUNT(*)
|
||||
1
|
||||
SELECT COUNT(*) FROM t1t;
|
||||
COUNT(*)
|
||||
1
|
||||
SELECT COUNT(*) FROM t1z;
|
||||
COUNT(*)
|
||||
1
|
||||
SELECT COUNT(*) FROM t5_7;
|
||||
COUNT(*)
|
||||
1
|
||||
SELECT COUNT(*) FROM t5_7b;
|
||||
COUNT(*)
|
||||
1
|
||||
SELECT COUNT(*) FROM t10_1;
|
||||
COUNT(*)
|
||||
1
|
||||
SELECT COUNT(*) FROM t10_1b;
|
||||
COUNT(*)
|
||||
1
|
||||
# restart
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
test.t1b check status OK
|
||||
test.t1t check status OK
|
||||
test.t1z check status OK
|
||||
test.t5_7 check note Auto_increment checked and .frm file version updated
|
||||
test.t5_7 check status OK
|
||||
test.t5_7b check note Auto_increment checked and .frm file version updated
|
||||
test.t5_7b check status OK
|
||||
test.t10_1 check note Auto_increment checked and .frm file version updated
|
||||
test.t10_1 check status OK
|
||||
test.t10_1b check note Auto_increment checked and .frm file version updated
|
||||
test.t10_1b check status OK
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1b VALUES(NULL);
|
||||
INSERT INTO t1t VALUES(NULL);
|
||||
INSERT INTO t1z VALUES(NULL);
|
||||
INSERT INTO t5_7 VALUES(NULL);
|
||||
INSERT INTO t5_7b VALUES(NULL);
|
||||
INSERT INTO t10_1 VALUES(NULL);
|
||||
INSERT INTO t10_1b VALUES(NULL);
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
test.t1b check status OK
|
||||
test.t1t check status OK
|
||||
test.t1z check status OK
|
||||
test.t5_7 check status OK
|
||||
test.t5_7b check status OK
|
||||
test.t10_1 check status OK
|
||||
test.t10_1b check status OK
|
||||
SELECT * FROM t1;
|
||||
id
|
||||
4
|
||||
42
|
||||
SELECT * FROM t1b;
|
||||
id
|
||||
3
|
||||
347
|
||||
SELECT * FROM t1t;
|
||||
id
|
||||
123
|
||||
124
|
||||
SELECT * FROM t1z;
|
||||
id
|
||||
42
|
||||
43
|
||||
SELECT * FROM t5_7;
|
||||
id
|
||||
42
|
||||
43
|
||||
SELECT * FROM t5_7b;
|
||||
id
|
||||
3
|
||||
347
|
||||
SELECT * FROM t10_1;
|
||||
id
|
||||
42
|
||||
43
|
||||
SELECT * FROM t10_1b;
|
||||
id
|
||||
3
|
||||
347
|
||||
DROP TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;
|
168
mysql-test/suite/innodb/t/autoinc_import.test
Normal file
168
mysql-test/suite/innodb/t/autoinc_import.test
Normal file
|
@ -0,0 +1,168 @@
|
|||
--source include/have_innodb.inc
|
||||
|
||||
CREATE TABLE t1 (id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(42);
|
||||
CREATE TABLE t1b LIKE t1;
|
||||
INSERT INTO t1b VALUES(3);
|
||||
CREATE TABLE t1z LIKE t1;
|
||||
CREATE TABLE t1t (id TINYINT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
|
||||
CREATE TABLE t0t LIKE t1t;
|
||||
INSERT INTO t1t VALUES(123);
|
||||
--let DATADIR=`select @@datadir`
|
||||
--let PAGE_SIZE=`select @@innodb_page_size`
|
||||
FLUSH TABLES t1,t1b,t1t FOR EXPORT;
|
||||
--copy_file $DATADIR/test/t1.ibd $DATADIR/test/t.ibd
|
||||
--copy_file $DATADIR/test/t1.ibd $DATADIR/test/tz.ibd
|
||||
--copy_file $DATADIR/test/t1b.ibd $DATADIR/test/tb.ibd
|
||||
--copy_file $DATADIR/test/t1t.ibd $DATADIR/test/tt.ibd
|
||||
UNLOCK TABLES;
|
||||
CREATE TABLE t5_7 LIKE t1;
|
||||
CREATE TABLE t5_7b LIKE t1b;
|
||||
CREATE TABLE t10_1 LIKE t1;
|
||||
CREATE TABLE t10_1b LIKE t1b;
|
||||
ALTER TABLE t1 DISCARD TABLESPACE;
|
||||
ALTER TABLE t1b DISCARD TABLESPACE;
|
||||
ALTER TABLE t1z DISCARD TABLESPACE;
|
||||
ALTER TABLE t1t DISCARD TABLESPACE;
|
||||
ALTER TABLE t0t DISCARD TABLESPACE;
|
||||
ALTER TABLE t5_7 DISCARD TABLESPACE;
|
||||
ALTER TABLE t5_7b DISCARD TABLESPACE;
|
||||
ALTER TABLE t10_1 DISCARD TABLESPACE;
|
||||
ALTER TABLE t10_1b DISCARD TABLESPACE;
|
||||
FLUSH TABLES;
|
||||
|
||||
# Update the PAGE_ROOT_AUTO_INC field of a few files.
|
||||
perl;
|
||||
do "$ENV{MTR_SUITE_DIR}/include/crc32.pl";
|
||||
sub update_autoinc
|
||||
{
|
||||
my ($file, $value) = @_;
|
||||
open(FILE, "+<$file") || die "Unable to open $file";
|
||||
binmode FILE;
|
||||
my $ps= $ENV{PAGE_SIZE};
|
||||
my $page;
|
||||
die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
|
||||
my $full_crc32 = unpack("N",substr($page,54,4)) & 0x10; # FIL_SPACE_FLAGS
|
||||
sysseek(FILE, 3*$ps, 0) || die "Unable to seek $file\n";
|
||||
die "Unable to read $file" unless sysread(FILE, $page, $ps) == $ps;
|
||||
substr($page,56,8)=pack("NN",0,$value);
|
||||
my $polynomial = 0x82f63b78; # CRC-32C
|
||||
if ($full_crc32) {
|
||||
my $ck = mycrc32(substr($page, 0, $ps-4), 0, $polynomial);
|
||||
substr($page, $ps-4, 4) = pack("N", $ck);
|
||||
}
|
||||
else
|
||||
{
|
||||
my $ck= pack("N",mycrc32(substr($page, 4, 22), 0, $polynomial) ^
|
||||
mycrc32(substr($page, 38, $ps - 38 - 8), 0, $polynomial));
|
||||
substr($page,0,4)=$ck;
|
||||
substr($page,$ps-8,4)=$ck;
|
||||
}
|
||||
sysseek(FILE, 3*$ps, 0) || die "Unable to rewind $file\n";
|
||||
syswrite(FILE, $page, $ps)==$ps || die "Unable to write $file\n";
|
||||
close(FILE) || die "Unable to close $file";
|
||||
}
|
||||
update_autoinc("$ENV{DATADIR}/test/tz.ibd", 0);
|
||||
update_autoinc("$ENV{DATADIR}/test/t.ibd", 3);
|
||||
update_autoinc("$ENV{DATADIR}/test/tb.ibd", 346);
|
||||
update_autoinc("$ENV{DATADIR}/test/tt.ibd", 128);
|
||||
EOF
|
||||
|
||||
--remove_file $DATADIR/test/t5_7.frm
|
||||
--remove_file $DATADIR/test/t5_7b.frm
|
||||
--copy_file $MYSQL_TEST_DIR/std_data/autoinc_import_57.frm $DATADIR/test/t5_7.frm
|
||||
--copy_file $MYSQL_TEST_DIR/std_data/autoinc_import_57.frm $DATADIR/test/t5_7b.frm
|
||||
--remove_file $DATADIR/test/t10_1.frm
|
||||
--remove_file $DATADIR/test/t10_1b.frm
|
||||
--copy_file $MYSQL_TEST_DIR/std_data/autoinc_import_101.frm $DATADIR/test/t10_1.frm
|
||||
--copy_file $MYSQL_TEST_DIR/std_data/autoinc_import_101.frm $DATADIR/test/t10_1b.frm
|
||||
--copy_file $DATADIR/test/t.ibd $DATADIR/test/t5_7.ibd
|
||||
--copy_file $DATADIR/test/tb.ibd $DATADIR/test/t5_7b.ibd
|
||||
--copy_file $DATADIR/test/t.ibd $DATADIR/test/t10_1.ibd
|
||||
--copy_file $DATADIR/test/tb.ibd $DATADIR/test/t10_1b.ibd
|
||||
--move_file $DATADIR/test/t.ibd $DATADIR/test/t1.ibd
|
||||
--move_file $DATADIR/test/tb.ibd $DATADIR/test/t1b.ibd
|
||||
--copy_file $DATADIR/test/tt.ibd $DATADIR/test/t0t.ibd
|
||||
--move_file $DATADIR/test/tt.ibd $DATADIR/test/t1t.ibd
|
||||
--move_file $DATADIR/test/tz.ibd $DATADIR/test/t1z.ibd
|
||||
|
||||
ALTER TABLE t0t IMPORT TABLESPACE;
|
||||
INSERT INTO t0t VALUES(NULL);
|
||||
SELECT * FROM t0t;
|
||||
DROP TABLE t0t;
|
||||
ALTER TABLE t1 IMPORT TABLESPACE;
|
||||
ALTER TABLE t1b IMPORT TABLESPACE;
|
||||
ALTER TABLE t1z IMPORT TABLESPACE;
|
||||
ALTER TABLE t1t IMPORT TABLESPACE;
|
||||
ALTER TABLE t5_7 IMPORT TABLESPACE;
|
||||
ALTER TABLE t5_7b IMPORT TABLESPACE;
|
||||
ALTER TABLE t10_1 IMPORT TABLESPACE;
|
||||
ALTER TABLE t10_1b IMPORT TABLESPACE;
|
||||
|
||||
--let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err
|
||||
--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 128 to 123 on table `test`\.`t0t`
|
||||
--source include/search_pattern_in_file.inc
|
||||
--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 0 to 42 on table `test`\.`t1z`
|
||||
--source include/search_pattern_in_file.inc
|
||||
--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 128 to 123 on table `test`\.`t1t`
|
||||
--source include/search_pattern_in_file.inc
|
||||
--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 3 to 42 on table `test`\.`t5_7` \(created with version 50744\)
|
||||
--source include/search_pattern_in_file.inc
|
||||
--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC from 3 to 42 on table `test`\.`t10_1` \(created with version 100149\)
|
||||
--source include/search_pattern_in_file.inc
|
||||
--let SEARCH_PATTERN= InnoDB: Resetting PAGE_ROOT_AUTO_INC
|
||||
--source include/search_pattern_in_file.inc
|
||||
|
||||
# Restart, so that the InnoDB tables will be loaded into the data dictionary.
|
||||
--let $restart_parameters=--read-only
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
|
||||
|
||||
--let $restart_parameters=--innodb-read-only --read-only
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
|
||||
|
||||
--let $restart_parameters=--innodb-read-only
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
|
||||
|
||||
SELECT COUNT(*) FROM t1;
|
||||
SELECT COUNT(*) FROM t1b;
|
||||
SELECT COUNT(*) FROM t1t;
|
||||
SELECT COUNT(*) FROM t1z;
|
||||
SELECT COUNT(*) FROM t5_7;
|
||||
SELECT COUNT(*) FROM t5_7b;
|
||||
SELECT COUNT(*) FROM t10_1;
|
||||
SELECT COUNT(*) FROM t10_1b;
|
||||
|
||||
--let $restart_parameters=
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
|
||||
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1b VALUES(NULL);
|
||||
INSERT INTO t1t VALUES(NULL);
|
||||
INSERT INTO t1z VALUES(NULL);
|
||||
INSERT INTO t5_7 VALUES(NULL);
|
||||
INSERT INTO t5_7b VALUES(NULL);
|
||||
INSERT INTO t10_1 VALUES(NULL);
|
||||
INSERT INTO t10_1b VALUES(NULL);
|
||||
|
||||
CHECK TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b FOR UPGRADE;
|
||||
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t1b;
|
||||
SELECT * FROM t1t;
|
||||
SELECT * FROM t1z;
|
||||
SELECT * FROM t5_7;
|
||||
SELECT * FROM t5_7b;
|
||||
SELECT * FROM t10_1;
|
||||
SELECT * FROM t10_1b;
|
||||
DROP TABLE t1, t1b, t1t, t1z, t5_7, t5_7b, t10_1, t10_1b;
|
|
@ -4669,7 +4669,7 @@ int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
|
|||
if (unlikely((error= check(thd, check_opt))))
|
||||
return error;
|
||||
/* Skip updating frm version if not main handler. */
|
||||
if (table->file != this)
|
||||
if (table->file != this || opt_readonly)
|
||||
return error;
|
||||
return update_frm_version(table);
|
||||
}
|
||||
|
@ -4718,7 +4718,7 @@ int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
|
|||
DBUG_ASSERT(result == HA_ADMIN_NOT_IMPLEMENTED ||
|
||||
ha_table_flags() & HA_CAN_REPAIR);
|
||||
|
||||
if (result == HA_ADMIN_OK)
|
||||
if (result == HA_ADMIN_OK && !opt_readonly)
|
||||
result= update_frm_version(table);
|
||||
return result;
|
||||
}
|
||||
|
@ -5659,7 +5659,7 @@ err:
|
|||
|
||||
void st_ha_check_opt::init()
|
||||
{
|
||||
flags= sql_flags= 0;
|
||||
flags= sql_flags= handler_flags= 0;
|
||||
start_time= my_time(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -2615,6 +2615,7 @@ typedef struct st_ha_check_opt
|
|||
st_ha_check_opt() = default; /* Remove gcc warning */
|
||||
uint flags; /* isam layer flags (e.g. for myisamchk) */
|
||||
uint sql_flags; /* sql layer flags - for something myisamchk cannot do */
|
||||
uint handler_flags; /* Reserved for handler usage */
|
||||
time_t start_time; /* When check/repair starts */
|
||||
KEY_CACHE *key_cache; /* new key cache when changing key cache */
|
||||
void init();
|
||||
|
|
|
@ -5665,6 +5665,40 @@ extern "C" void *thd_mdl_context(MYSQL_THD thd)
|
|||
return &thd->mdl_context;
|
||||
}
|
||||
|
||||
/**
|
||||
Send check/repair message to the user
|
||||
|
||||
@param op one of check or repair
|
||||
@param msg_type one of info, warning or error
|
||||
@param print_to_log <> 0 if we should also print the message to error log.
|
||||
*/
|
||||
|
||||
extern "C" void
|
||||
print_check_msg(THD *thd, const char *db_name, const char *table_name, const char *op,
|
||||
const char *msg_type, const char *message, my_bool print_to_log)
|
||||
{
|
||||
char name[NAME_LEN * 2 + 2];
|
||||
Protocol *protocol= thd->protocol;
|
||||
|
||||
DBUG_ASSERT(strlen(db_name) <= NAME_LEN);
|
||||
DBUG_ASSERT(strlen(table_name) <= NAME_LEN);
|
||||
|
||||
size_t length= size_t(strxnmov(name, sizeof name - 1,
|
||||
db_name, ".", table_name, NullS) -
|
||||
name);
|
||||
protocol->prepare_for_resend();
|
||||
protocol->store(name, length, system_charset_info);
|
||||
protocol->store(op, system_charset_info);
|
||||
protocol->store(msg_type, system_charset_info);
|
||||
protocol->store(message, system_charset_info);
|
||||
if (protocol->write())
|
||||
sql_print_error("Failed on my_net_write, writing to stderr instead: %s: %s\n",
|
||||
table_name, message);
|
||||
else if (thd->variables.log_warnings > 2 && print_to_log)
|
||||
sql_print_error("%s: table '%s' got '%s' during %s",
|
||||
msg_type, table_name, message, op);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Handling of statement states in functions and triggers.
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <service_versions.h>
|
||||
#include <mysql/service_wsrep.h>
|
||||
#include <mysql/service_thd_mdl.h>
|
||||
#include <mysql/service_print_check_msg.h>
|
||||
|
||||
struct st_service_ref {
|
||||
const char *name;
|
||||
|
@ -217,6 +218,11 @@ static struct my_print_error_service_st my_print_error_handler=
|
|||
my_printv_error
|
||||
};
|
||||
|
||||
static struct print_check_msg_service_st print_check_msg_handler=
|
||||
{
|
||||
print_check_msg
|
||||
};
|
||||
|
||||
struct json_service_st json_handler=
|
||||
{
|
||||
json_type,
|
||||
|
@ -264,6 +270,7 @@ static struct st_service_ref list_of_services[]=
|
|||
{ "my_crypt_service", VERSION_my_crypt, &crypt_handler},
|
||||
{ "my_md5_service", VERSION_my_md5, &my_md5_handler},
|
||||
{ "my_print_error_service", VERSION_my_print_error, &my_print_error_handler},
|
||||
{ "print_check_msg_service", VERSION_print_check_msg, &print_check_msg_handler},
|
||||
{ "my_sha1_service", VERSION_my_sha1, &my_sha1_handler},
|
||||
{ "my_sha2_service", VERSION_my_sha2, &my_sha2_handler},
|
||||
{ "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler },
|
||||
|
|
|
@ -43,6 +43,7 @@ Created 6/2/1994 Heikki Tuuri
|
|||
#include "gis0geo.h"
|
||||
#include "dict0boot.h"
|
||||
#include "row0sel.h" /* row_search_max_autoinc() */
|
||||
#include "log.h"
|
||||
|
||||
Atomic_counter<uint32_t> btr_validate_index_running;
|
||||
|
||||
|
@ -1267,53 +1268,71 @@ btr_read_autoinc(dict_index_t* index)
|
|||
return autoinc;
|
||||
}
|
||||
|
||||
dict_index_t *dict_table_t::get_index(const dict_col_t &col) const
|
||||
{
|
||||
dict_index_t *index= dict_table_get_first_index(this);
|
||||
|
||||
while (index && (index->fields[0].col != &col || index->is_corrupted()))
|
||||
index= dict_table_get_next_index(index);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/** Read the last used AUTO_INCREMENT value from PAGE_ROOT_AUTO_INC,
|
||||
or fall back to MAX(auto_increment_column).
|
||||
@param[in] table table containing an AUTO_INCREMENT column
|
||||
@param[in] col_no index of the AUTO_INCREMENT column
|
||||
@return the AUTO_INCREMENT value
|
||||
@retval 0 on error or if no AUTO_INCREMENT value was used yet */
|
||||
ib_uint64_t
|
||||
btr_read_autoinc_with_fallback(const dict_table_t* table, unsigned col_no)
|
||||
@param table table containing an AUTO_INCREMENT column
|
||||
@param col_no index of the AUTO_INCREMENT column
|
||||
@param mysql_version TABLE_SHARE::mysql_version
|
||||
@param max the maximum value of the AUTO_INCREMENT column
|
||||
@return the AUTO_INCREMENT value
|
||||
@retval 0 on error or if no AUTO_INCREMENT value was used yet */
|
||||
uint64_t btr_read_autoinc_with_fallback(const dict_table_t *table,
|
||||
unsigned col_no, ulong mysql_version,
|
||||
uint64_t max)
|
||||
{
|
||||
ut_ad(table->persistent_autoinc);
|
||||
ut_ad(!table->is_temporary());
|
||||
ut_ad(table->persistent_autoinc);
|
||||
ut_ad(!table->is_temporary());
|
||||
|
||||
dict_index_t* index = dict_table_get_first_index(table);
|
||||
uint64_t autoinc= 0;
|
||||
mtr_t mtr;
|
||||
mtr.start();
|
||||
|
||||
if (index == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (buf_block_t *block=
|
||||
buf_page_get(page_id_t(table->space_id,
|
||||
dict_table_get_first_index(table)->page),
|
||||
table->space->zip_size(), RW_SX_LATCH, &mtr))
|
||||
{
|
||||
autoinc= page_get_autoinc(block->frame);
|
||||
|
||||
mtr_t mtr;
|
||||
mtr.start();
|
||||
buf_block_t* block = buf_page_get(
|
||||
page_id_t(index->table->space_id, index->page),
|
||||
index->table->space->zip_size(),
|
||||
RW_S_LATCH, &mtr);
|
||||
if (autoinc > 0 && autoinc <= max && mysql_version >= 100210);
|
||||
else if (dict_index_t *index=
|
||||
table->get_index(*dict_table_get_nth_col(table, col_no)))
|
||||
{
|
||||
/* Read MAX(autoinc_col), in case this table had originally been
|
||||
created before MariaDB 10.2.4 introduced persistent AUTO_INCREMENT
|
||||
and MariaDB 10.2.10 fixed MDEV-12123, and there could be a garbage
|
||||
value in the PAGE_ROOT_AUTO_INC field. */
|
||||
const uint64_t max_autoinc= row_search_max_autoinc(index);
|
||||
const bool need_adjust{autoinc > max || autoinc < max_autoinc};
|
||||
ut_ad(max_autoinc <= max);
|
||||
|
||||
ib_uint64_t autoinc = block ? page_get_autoinc(block->frame) : 0;
|
||||
const bool retry = block && autoinc == 0
|
||||
&& !page_is_empty(block->frame);
|
||||
mtr.commit();
|
||||
if (UNIV_UNLIKELY(need_adjust) && !high_level_read_only && !opt_readonly)
|
||||
{
|
||||
sql_print_information("InnoDB: Resetting PAGE_ROOT_AUTO_INC from "
|
||||
UINT64PF " to " UINT64PF
|
||||
" on table %`.*s.%`s (created with version %lu)",
|
||||
autoinc, max_autoinc,
|
||||
int(table->name.dblen()), table->name.m_name,
|
||||
table->name.basename(), mysql_version);
|
||||
autoinc= max_autoinc;
|
||||
index->set_modified(mtr);
|
||||
page_set_autoinc(block, max_autoinc, &mtr, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (retry) {
|
||||
/* This should be an old data file where
|
||||
PAGE_ROOT_AUTO_INC was initialized to 0.
|
||||
Fall back to reading MAX(autoinc_col).
|
||||
There should be an index on it. */
|
||||
const dict_col_t* autoinc_col
|
||||
= dict_table_get_nth_col(table, col_no);
|
||||
while (index && index->fields[0].col != autoinc_col) {
|
||||
index = dict_table_get_next_index(index);
|
||||
}
|
||||
|
||||
if (index) {
|
||||
autoinc = row_search_max_autoinc(index);
|
||||
}
|
||||
}
|
||||
|
||||
return autoinc;
|
||||
mtr.commit();
|
||||
return autoinc;
|
||||
}
|
||||
|
||||
/** Write the next available AUTO_INCREMENT value to PAGE_ROOT_AUTO_INC.
|
||||
|
|
|
@ -54,10 +54,13 @@ this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include <my_bitmap.h>
|
||||
#include <mysql/service_thd_alloc.h>
|
||||
#include <mysql/service_thd_wait.h>
|
||||
#include <mysql/service_print_check_msg.h>
|
||||
#include "sql_type_geom.h"
|
||||
#include "scope.h"
|
||||
#include "srv0srv.h"
|
||||
|
||||
extern my_bool opt_readonly;
|
||||
|
||||
// MYSQL_PLUGIN_IMPORT extern my_bool lower_case_file_system;
|
||||
// MYSQL_PLUGIN_IMPORT extern char mysql_unpacked_real_data_home[];
|
||||
|
||||
|
@ -117,6 +120,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "row0ext.h"
|
||||
|
||||
#include <limits>
|
||||
#include <myisamchk.h> // TT_FOR_UPGRADE
|
||||
|
||||
#define thd_get_trx_isolation(X) ((enum_tx_isolation)thd_tx_isolation(X))
|
||||
|
||||
|
@ -5620,14 +5624,10 @@ func_exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Get the upper limit of the MySQL integral and floating-point type.
|
||||
@return maximum allowed value for the field */
|
||||
UNIV_INTERN
|
||||
ulonglong
|
||||
innobase_get_int_col_max_value(
|
||||
/*===========================*/
|
||||
const Field* field) /*!< in: MySQL field */
|
||||
/** Get the maximum integer value of a numeric column.
|
||||
@param field column definition
|
||||
@return maximum allowed integer value */
|
||||
ulonglong innobase_get_int_col_max_value(const Field *field)
|
||||
{
|
||||
ulonglong max_value = 0;
|
||||
|
||||
|
@ -5691,46 +5691,45 @@ ha_innobase::open().
|
|||
|
||||
@param[in,out] table persistent table
|
||||
@param[in] field the AUTO_INCREMENT column */
|
||||
static
|
||||
void
|
||||
initialize_auto_increment(dict_table_t* table, const Field* field)
|
||||
static void initialize_auto_increment(dict_table_t *table, const Field& field,
|
||||
const TABLE_SHARE &s)
|
||||
{
|
||||
ut_ad(!table->is_temporary());
|
||||
ut_ad(!table->is_temporary());
|
||||
const unsigned col_no= innodb_col_no(&field);
|
||||
table->autoinc_mutex.lock();
|
||||
table->persistent_autoinc=
|
||||
uint16_t(dict_table_get_nth_col_pos(table, col_no, nullptr) + 1) &
|
||||
dict_index_t::MAX_N_FIELDS;
|
||||
if (table->autoinc)
|
||||
/* Already initialized. Our caller checked
|
||||
table->persistent_autoinc without
|
||||
autoinc_mutex protection, and there might be multiple
|
||||
ha_innobase::open() executing concurrently. */;
|
||||
else if (srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN)
|
||||
/* If innodb_force_recovery is set so high that writes
|
||||
are disabled we force the AUTOINC counter to 0
|
||||
value effectively disabling writes to the table.
|
||||
Secondly, we avoid reading the table in case the read
|
||||
results in failure due to a corrupted table/index.
|
||||
|
||||
const unsigned col_no = innodb_col_no(field);
|
||||
We will not return an error to the client, so that the
|
||||
tables can be dumped with minimal hassle. If an error
|
||||
were returned in this case, the first attempt to read
|
||||
the table would fail and subsequent SELECTs would succeed. */;
|
||||
else if (table->persistent_autoinc)
|
||||
{
|
||||
uint64_t max_value= innobase_get_int_col_max_value(&field);
|
||||
table->autoinc=
|
||||
innobase_next_autoinc(btr_read_autoinc_with_fallback(table, col_no,
|
||||
s.mysql_version,
|
||||
max_value),
|
||||
1 /* need */,
|
||||
1 /* auto_increment_increment */,
|
||||
0 /* auto_increment_offset */,
|
||||
max_value);
|
||||
}
|
||||
|
||||
table->autoinc_mutex.lock();
|
||||
|
||||
table->persistent_autoinc = static_cast<uint16_t>(
|
||||
dict_table_get_nth_col_pos(table, col_no, NULL) + 1)
|
||||
& dict_index_t::MAX_N_FIELDS;
|
||||
|
||||
if (table->autoinc) {
|
||||
/* Already initialized. Our caller checked
|
||||
table->persistent_autoinc without
|
||||
autoinc_mutex protection, and there might be multiple
|
||||
ha_innobase::open() executing concurrently. */
|
||||
} else if (srv_force_recovery > SRV_FORCE_NO_IBUF_MERGE) {
|
||||
/* If the recovery level is set so high that writes
|
||||
are disabled we force the AUTOINC counter to 0
|
||||
value effectively disabling writes to the table.
|
||||
Secondly, we avoid reading the table in case the read
|
||||
results in failure due to a corrupted table/index.
|
||||
|
||||
We will not return an error to the client, so that the
|
||||
tables can be dumped with minimal hassle. If an error
|
||||
were returned in this case, the first attempt to read
|
||||
the table would fail and subsequent SELECTs would succeed. */
|
||||
} else if (table->persistent_autoinc) {
|
||||
table->autoinc = innobase_next_autoinc(
|
||||
btr_read_autoinc_with_fallback(table, col_no),
|
||||
1 /* need */,
|
||||
1 /* auto_increment_increment */,
|
||||
0 /* auto_increment_offset */,
|
||||
innobase_get_int_col_max_value(field));
|
||||
}
|
||||
|
||||
table->autoinc_mutex.unlock();
|
||||
table->autoinc_mutex.unlock();
|
||||
}
|
||||
|
||||
/** Open an InnoDB table
|
||||
|
@ -5966,7 +5965,7 @@ ha_innobase::open(const char* name, int, uint)
|
|||
|| m_prebuilt->table->persistent_autoinc
|
||||
|| !m_prebuilt->table->is_readable()) {
|
||||
} else if (const Field* ai = table->found_next_number_field) {
|
||||
initialize_auto_increment(m_prebuilt->table, ai);
|
||||
initialize_auto_increment(m_prebuilt->table, *ai, *table->s);
|
||||
}
|
||||
|
||||
/* Set plugin parser for fulltext index */
|
||||
|
@ -14822,12 +14821,34 @@ ha_innobase::check(
|
|||
ulint n_rows_in_table = ULINT_UNDEFINED;
|
||||
bool is_ok = true;
|
||||
dberr_t ret;
|
||||
uint handler_flags= check_opt->handler_flags;
|
||||
|
||||
DBUG_ENTER("ha_innobase::check");
|
||||
DBUG_ASSERT(thd == ha_thd());
|
||||
ut_a(m_prebuilt->trx->magic_n == TRX_MAGIC_N);
|
||||
ut_a(m_prebuilt->trx == thd_to_trx(thd));
|
||||
|
||||
if (handler_flags || check_for_upgrade(check_opt)) {
|
||||
/* The file was already checked and fixed as part of open */
|
||||
print_check_msg(thd, table->s->db.str, table->s->table_name.str,
|
||||
"check", "note",
|
||||
(opt_readonly || high_level_read_only
|
||||
|| !(check_opt->sql_flags & TT_FOR_UPGRADE))
|
||||
? "Auto_increment will be"
|
||||
" checked on each open until"
|
||||
" CHECK TABLE FOR UPGRADE is executed"
|
||||
: "Auto_increment checked and"
|
||||
" .frm file version updated", 1);
|
||||
if (handler_flags && (check_opt->sql_flags & TT_FOR_UPGRADE)) {
|
||||
/*
|
||||
No other issues found (as handler_flags was only
|
||||
set if there as not other problems with the table
|
||||
than auto_increment).
|
||||
*/
|
||||
DBUG_RETURN(HA_ADMIN_OK);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_prebuilt->mysql_template == NULL) {
|
||||
/* Build the template; we will use a dummy template
|
||||
in index scans done in checking */
|
||||
|
@ -15053,6 +15074,35 @@ ha_innobase::check(
|
|||
DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);
|
||||
}
|
||||
|
||||
/**
|
||||
Check if we there is a problem with the InnoDB table.
|
||||
@param check_opt check options
|
||||
@retval HA_ADMIN_OK if Table is ok
|
||||
@retval HA_ADMIN_NEEDS_ALTER User should run ALTER TABLE FOR UPGRADE
|
||||
@retval HA_ADMIN_NEEDS_CHECK User should run CHECK TABLE FOR UPGRADE
|
||||
@retval HA_ADMIN_FAILED if InnoDB is in read-only mode */
|
||||
int ha_innobase::check_for_upgrade(HA_CHECK_OPT *check_opt)
|
||||
{
|
||||
/*
|
||||
Check if there is a possibility that the auto increment value
|
||||
stored in PAGE_ROOT_AUTO_INC could be corrupt.
|
||||
*/
|
||||
if (table->s->mysql_version >= 100210);
|
||||
else if (const Field *auto_increment= table->found_next_number_field)
|
||||
{
|
||||
uint col_no= innodb_col_no(auto_increment);
|
||||
const dict_col_t *autoinc_col=
|
||||
dict_table_get_nth_col(m_prebuilt->table, col_no);
|
||||
if (m_prebuilt->table->get_index(*autoinc_col))
|
||||
{
|
||||
check_opt->handler_flags= 1;
|
||||
return (high_level_read_only && !opt_readonly)
|
||||
? HA_ADMIN_FAILED : HA_ADMIN_NEEDS_CHECK;
|
||||
}
|
||||
}
|
||||
return HA_ADMIN_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Gets the foreign key create info for a table stored in InnoDB.
|
||||
@return own: character string in the form which can be inserted to the
|
||||
|
|
|
@ -207,6 +207,7 @@ public:
|
|||
int rename_table(const char* from, const char* to) override;
|
||||
inline int defragment_table(const char* name);
|
||||
int check(THD* thd, HA_CHECK_OPT* check_opt) override;
|
||||
int check_for_upgrade(HA_CHECK_OPT* check_opt) override;
|
||||
|
||||
inline void reload_statistics();
|
||||
|
||||
|
@ -944,6 +945,12 @@ unsigned
|
|||
innodb_col_no(const Field* field)
|
||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||
|
||||
/** Get the maximum integer value of a numeric column.
|
||||
@param field column definition
|
||||
@return maximum allowed integer value */
|
||||
ulonglong innobase_get_int_col_max_value(const Field *field)
|
||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||
|
||||
/********************************************************************//**
|
||||
Helper function to push frm mismatch error to error log and
|
||||
if needed to sql-layer. */
|
||||
|
|
|
@ -1179,15 +1179,6 @@ private:
|
|||
ha_innobase_inplace_ctx& operator=(const ha_innobase_inplace_ctx&);
|
||||
};
|
||||
|
||||
/********************************************************************//**
|
||||
Get the upper limit of the MySQL integral and floating-point type.
|
||||
@return maximum allowed value for the field */
|
||||
UNIV_INTERN
|
||||
ulonglong
|
||||
innobase_get_int_col_max_value(
|
||||
/*===========================*/
|
||||
const Field* field); /*!< in: MySQL field */
|
||||
|
||||
/* Report an InnoDB error to the client by invoking my_error(). */
|
||||
static ATTRIBUTE_COLD __attribute__((nonnull))
|
||||
void
|
||||
|
@ -9736,13 +9727,7 @@ commit_set_autoinc(
|
|||
const dict_col_t* autoinc_col
|
||||
= dict_table_get_nth_col(ctx->old_table,
|
||||
innodb_col_no(ai));
|
||||
dict_index_t* index
|
||||
= dict_table_get_first_index(ctx->old_table);
|
||||
while (index != NULL
|
||||
&& index->fields[0].col != autoinc_col) {
|
||||
index = dict_table_get_next_index(index);
|
||||
}
|
||||
|
||||
auto index = ctx->old_table->get_index(*autoinc_col);
|
||||
ut_ad(index);
|
||||
|
||||
ib_uint64_t max_in_table = index
|
||||
|
|
|
@ -372,13 +372,16 @@ btr_read_autoinc(dict_index_t* index)
|
|||
|
||||
/** Read the last used AUTO_INCREMENT value from PAGE_ROOT_AUTO_INC,
|
||||
or fall back to MAX(auto_increment_column).
|
||||
@param[in] table table containing an AUTO_INCREMENT column
|
||||
@param[in] col_no index of the AUTO_INCREMENT column
|
||||
@return the AUTO_INCREMENT value
|
||||
@retval 0 on error or if no AUTO_INCREMENT value was used yet */
|
||||
ib_uint64_t
|
||||
btr_read_autoinc_with_fallback(const dict_table_t* table, unsigned col_no)
|
||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||
@param table table containing an AUTO_INCREMENT column
|
||||
@param col_no index of the AUTO_INCREMENT column
|
||||
@param mysql_version TABLE_SHARE::mysql_version
|
||||
@param max the maximum value of the AUTO_INCREMENT column
|
||||
@return the AUTO_INCREMENT value
|
||||
@retval 0 on error or if no AUTO_INCREMENT value was used yet */
|
||||
uint64_t btr_read_autoinc_with_fallback(const dict_table_t *table,
|
||||
unsigned col_no, ulong mysql_version,
|
||||
uint64_t max)
|
||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||
|
||||
/** Write the next available AUTO_INCREMENT value to PAGE_ROOT_AUTO_INC.
|
||||
@param[in,out] index clustered index
|
||||
|
|
|
@ -2366,6 +2366,9 @@ public:
|
|||
|
||||
/** @return number of unique columns in FTS_DOC_ID index */
|
||||
unsigned fts_n_uniq() const { return versioned() ? 2 : 1; }
|
||||
|
||||
/** @return the index for that starts with a specific column */
|
||||
dict_index_t *get_index(const dict_col_t &col) const;
|
||||
};
|
||||
|
||||
inline void dict_index_t::set_modified(mtr_t& mtr) const
|
||||
|
|
|
@ -48,6 +48,8 @@ Created 2012-02-08 by Sunny Bains.
|
|||
#include "snappy-c.h"
|
||||
#endif
|
||||
#include "log.h"
|
||||
#include "table.h"
|
||||
#include "ha_innodb.h"
|
||||
|
||||
#include "scope.h"
|
||||
|
||||
|
@ -4333,6 +4335,37 @@ fil_tablespace_iterate(
|
|||
return(err);
|
||||
}
|
||||
|
||||
static void row_import_autoinc(dict_table_t *table, row_prebuilt_t *prebuilt,
|
||||
uint64_t autoinc)
|
||||
{
|
||||
if (!table->persistent_autoinc)
|
||||
{
|
||||
ut_ad(!autoinc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (autoinc)
|
||||
{
|
||||
btr_write_autoinc(dict_table_get_first_index(table), autoinc - 1);
|
||||
autoinc_set:
|
||||
table->autoinc= autoinc;
|
||||
sql_print_information("InnoDB: %`.*s.%`s autoinc value set to " UINT64PF,
|
||||
int(table->name.dblen()), table->name.m_name,
|
||||
table->name.basename(), autoinc);
|
||||
}
|
||||
else if (TABLE *t= prebuilt->m_mysql_table)
|
||||
{
|
||||
if (const Field *ai= t->found_next_number_field)
|
||||
{
|
||||
autoinc= 1 +
|
||||
btr_read_autoinc_with_fallback(table, innodb_col_no(ai),
|
||||
t->s->mysql_version,
|
||||
innobase_get_int_col_max_value(ai));
|
||||
goto autoinc_set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Imports a tablespace. The space id in the .ibd file must match the space id
|
||||
of the table in the data dictionary.
|
||||
|
@ -4719,16 +4752,7 @@ row_import_for_mysql(
|
|||
|
||||
/* Set autoinc value read from .cfg file, if one was specified.
|
||||
Otherwise, read the PAGE_ROOT_AUTO_INC and set it to table autoinc. */
|
||||
if (autoinc) {
|
||||
ib::info() << table->name << " autoinc value set to "
|
||||
<< autoinc;
|
||||
|
||||
table->autoinc = autoinc--;
|
||||
btr_write_autoinc(dict_table_get_first_index(table), autoinc);
|
||||
} else if (table->persistent_autoinc) {
|
||||
autoinc = btr_read_autoinc(dict_table_get_first_index(table));
|
||||
table->autoinc = ++autoinc;
|
||||
}
|
||||
row_import_autoinc(table, prebuilt, autoinc);
|
||||
|
||||
return(row_import_cleanup(prebuilt, trx, err));
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ C_MODE_END
|
|||
#include "key.h"
|
||||
#include "log.h"
|
||||
#include "sql_parse.h"
|
||||
#include "mysql/service_print_check_msg.h"
|
||||
|
||||
/*
|
||||
Note that in future versions, only *transactional* Maria tables can
|
||||
|
@ -427,10 +428,8 @@ static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type,
|
|||
const char *fmt, va_list args)
|
||||
{
|
||||
THD *thd= (THD *) param->thd;
|
||||
Protocol *protocol= thd->protocol;
|
||||
size_t length, msg_length;
|
||||
size_t msg_length __attribute__((unused));
|
||||
char msgbuf[MYSQL_ERRMSG_SIZE];
|
||||
char name[NAME_LEN * 2 + 2];
|
||||
|
||||
if (param->testflag & T_SUPPRESS_ERR_HANDLING)
|
||||
return;
|
||||
|
@ -459,27 +458,10 @@ static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type,
|
|||
_ma_check_print(param, msg_type, msgbuf);
|
||||
return;
|
||||
}
|
||||
length= (uint) (strxmov(name, param->db_name, ".", param->table_name,
|
||||
NullS) - name);
|
||||
/*
|
||||
TODO: switch from protocol to push_warning here. The main reason we didn't
|
||||
it yet is parallel repair, which threads have no THD object accessible via
|
||||
current_thd.
|
||||
|
||||
Also we likely need to lock mutex here (in both cases with protocol and
|
||||
push_warning).
|
||||
*/
|
||||
protocol->prepare_for_resend();
|
||||
protocol->store(name, (uint)length, system_charset_info);
|
||||
protocol->store(param->op_name, system_charset_info);
|
||||
protocol->store(msg_type, system_charset_info);
|
||||
protocol->store(msgbuf, (uint)msg_length, system_charset_info);
|
||||
if (protocol->write())
|
||||
sql_print_error("Failed on my_net_write, writing to stderr instead: %s.%s: %s\n",
|
||||
param->db_name, param->table_name, msgbuf);
|
||||
else if (thd->variables.log_warnings > 2)
|
||||
print_check_msg(thd, param->db_name, param->table_name,
|
||||
param->op_name, msg_type, msgbuf, 0);
|
||||
if (thd->variables.log_warnings > 2)
|
||||
_ma_check_print(param, msg_type, msgbuf);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue