Commit d6ea03fa authored by Daniel Black's avatar Daniel Black

MDEV-23630: mysqldump logically dump system table information

Add --system={all, users, plugins, udfs, servers, stats, timezones}

This will dump system information from the server in
a logical form like:
* CREATE USER
* GRANT
* SET DEFAULT ROLE
* CREATE ROLE
* CREATE SERVER
* INSTALL PLUGIN
* CREATE FUNCTION

"stats" is the innodb statistics tables or EITS and
these are dumped as INSERT/REPLACE INTO statements
without recreating the table.

"timezones" is the collection of timezone tables
which are important to transfer to generate identical
results on restoration.

Two other options have an effect on the SQL generated by
--system=all. These are mutually exclusive of each other.
* --replace
* --insert-ignore

--replace will include "OR REPLACE" into the logical form
like:
* CREATE OR REPLACE USER ...
* DROP ROLE IF EXISTS (MySQL-8.0+)
* CREATE OR REPLACE ROLE ...
* UNINSTALL PLUGIN IF EXISTS (10.4+) ... (before INSTALL PLUGIN)
* DROP FUNCTION IF EXISTS (MySQL-5.7+)
* CREATE OR REPLACE [AGGREGATE] FUNCTION
* CREATE OR REPLACE SERVER

--insert-ignore uses the construct " IF NOT EXISTS" where
supported in the logical syntax.

'CREATE OR REPLACE USER' includes protection against
being run as the same user that is importing the mysqldump.

Includes experimental support for dumping mysql-5.7/8.0
system tables and exporting logical SQL compatible with MySQL.

Updates mysqldump man page, including this information and
(removing obsolute bug reference)

Reviewed-by: anel@mariadb.org
parent c7902186
This diff is collapsed.
'\" t
.\"
.TH "\FBMYSQLDUMP\FR" "1" "3 April 2017" "MariaDB 10\&.2" "MariaDB Database System"
.TH "\FBMYSQLDUMP\FR" "1" "24 October 2020" "MariaDB 10\&.2" "MariaDB Database System"
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
......@@ -36,7 +36,7 @@ tables, consider using the
instead because it can accomplish faster backups and faster restores\&. See
\fBmysqlhotcopy\fR(1)\&.
.PP
There are three general ways to invoke
There are four general ways to invoke
\fBmysqldump\fR:
.sp
.if n \{\
......@@ -46,6 +46,7 @@ There are three general ways to invoke
shell> \fBmysqldump [\fR\fB\fIoptions\fR\fR\fB] \fR\fB\fIdb_name\fR\fR\fB [\fR\fB\fItbl_name\fR\fR\fB \&.\&.\&.]\fR
shell> \fBmysqldump [\fR\fB\fIoptions\fR\fR\fB] \-\-databases \fR\fB\fIdb_name\fR\fR\fB \&.\&.\&.\fR
shell> \fBmysqldump [\fR\fB\fIoptions\fR\fR\fB] \-\-all\-databases\fR
shell> \fBmysqldump [\fR\fB\fIoptions\fR\fR\fB] \-\-system={options}\fR
.fi
.if n \{\
.RE
......@@ -2192,6 +2193,110 @@ Verify server's "Common Name" in its cert against hostname used when connecting.
.sp -1
.IP \(bu 2.3
.\}
.\" mysqladmin: Dump system tables option
.\" Dump system tables option: mysqladmin
\fB\-\-system=\fR\fB\fI{all, users, plugins, udfs, servers, stats, timezones}\fR\fR
.sp
Dump the system tables in the mysql database in a logical form\&. This option is an empty set by default\&.
.sp
One or more options can be listed in comma separated list\&.
.sp
The options here are:
.sp
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
all \- an alias to enabling all of the below options\&.
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
users \- the users, roles and their grants outputed as \fBCREATE USER\fB, \fBCREATE ROLE\fR, \fBGRANT\fR, and \fBSET DEFAULT ROLE\fR (\fBALTER USER\fR for MySQL-8.0+)\&.
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
plugins \- active plugins of the server outputed as \fBINSTALL PLUGIN\fR\&.
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
udfs \- user define functions outputed as \fBCREATE FUNCTION\fR\&.
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
servers \- remote (federated) servers as \fBCREATE SERVER\fR\&.
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
stats \- statistics tables, InnoDB and Engine Independent Table Statistics (EITS), are dumped as \fBINSERT\fR/\fBREPLACE INFO\fR statements without (re)creating tables\&.
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
timezones \- timezone related system tables dumped as \fBINSERT\fR/\fBREPLACE INTO\fR statements without (re)creating tables\&.
.RE
.sp
The format of the output is affected by \fB\-\-replace\fR and \fB\-\-insert\-into\fR\&. The \fB\-\-replace\fR option will output \fBCREATE OR REPLACE\fR
forms of SQL, and also \fBDROP IF EXISTS\fR prior to \fBCREATE\fR, if a \fBCREATE OR REPLACE\fR option isn't available.
.sp
With \fB\-\-system=user\fR (or \fBall\fR), and \fB\-\-replace\fR, SQL is generated to generate an error if attempting to import the dump with a connection user that is being replaced within the dump\&.
.sp
The \fB\-\-insert\-into\fR option will cause \fBCREATE IF NOT EXIST\fR forms of SQL to generated if available.
.sp
For stats, and timezones, \fB\-\-replace\fR and \fB\-\-insert\-info\fR have the usual effects.
.sp
Enabling specific options here will cause the relevant tables in the mysql database to be ignored when dumping the mysql database or \fB\-\-all\-databases\fR\&.
.sp
Experimentally this option is designed to be able to dump system information from MySQL-5\&.7 and 8\&.0 servers\&. SQL generated is also
experimentally compatible with MySQL-5\&.7/8\&.0\&. Mappings of implemenation specific grants/plugins isn't always one-to-one however\&.
.sp
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.sp -1
.IP \(bu 2.3
.\}
.\" mysqldump: tab option
.\" tab option: mysqldump
\fB\-\-tab=\fR\fB\fIpath\fR\fR,
......@@ -2673,7 +2778,7 @@ If you encounter problems backing up views, please read the section that covers
.SH "COPYRIGHT"
.br
.PP
Copyright 2007-2008 MySQL AB, 2008-2010 Sun Microsystems, Inc., 2010-2015 MariaDB Foundation
Copyright 2007-2008 MySQL AB, 2008-2010 Sun Microsystems, Inc., 2010-2020 MariaDB Foundation
.PP
This documentation is free software; you can redistribute it and/or modify it only under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License.
.PP
......@@ -2681,12 +2786,6 @@ This documentation is distributed in the hope that it will be useful, but WITHOU
.PP
You should have received a copy of the GNU General Public License along with the program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA or see http://www.gnu.org/licenses/.
.sp
.SH "NOTES"
.IP " 1." 4
Bug#30123
.RS 4
\%http://bugs.mysql.com/bug.php?id=30123
.RE
.SH "SEE ALSO"
For more information, please refer to the MariaDB Knowledge Base, available online at https://mariadb.com/kb/
.SH AUTHOR
......
diff --git a/mysql-test/r/mysqldump-system.result b/mysql-test/r/mysqldump-system.result
index 88cf950c621..5f8b579fa67 100644
--- a/mysql-test/r/mysqldump-system.result
+++ b/mysql-test/r/mysqldump-system.result
@@ -7,8 +7,6 @@
delete from mysql.user where host not in ('localhost');
flush privileges;
create user USER;
-install plugin /*M!100401 IF NOT EXISTS */ unix_socket soname 'auth_socket.so';;
-alter user USER identified via unix_socket;
CREATE ROLE role_1;
CREATE ROLE role_2 WITH ADMIN role_1;
GRANT SHOW DATABASES ON *.* TO role_1;
@@ -48,9 +46,8 @@
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-INSTALL PLUGIN unix_socket SONAME 'auth_socket.so';
CREATE USER 'root'@'localhost';
-CREATE USER 'USER'@'%' IDENTIFIED VIA unix_socket;
+CREATE USER 'USER'@'%';
SELECT COALESCE(CURRENT_ROLE(),'NONE') into @current_role;
CREATE ROLE IF NOT EXISTS mariadb_dump_import_role;
GRANT mariadb_dump_import_role TO CURRENT_USER();
@@ -68,7 +65,7 @@
/*!80001 ALTER USER 'root'@'localhost' DEFAULT ROLE NONE */;
GRANT role_1 TO 'USER'@'%';
GRANT role_2 TO 'USER'@'%';
-GRANT USAGE ON *.* TO 'USER'@'%' IDENTIFIED VIA unix_socket;
+GRANT USAGE ON *.* TO 'USER'@'%';
/*M!100005 SET DEFAULT ROLE 'role_2' FOR 'USER'@'%' */;
/*!80001 ALTER USER 'USER'@'%' DEFAULT ROLE 'role_2' */;
GRANT role_2 TO 'role_1' WITH ADMIN OPTION;
@@ -168,8 +165,6 @@
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-/*M!100401 UNINSTALL PLUGIN IF EXIST unix_socket */;
-INSTALL PLUGIN unix_socket SONAME 'auth_socket.so';
DELIMITER |
/*M!100101 IF current_user()="'root'@'localhost'" THEN
SIGNAL SQLSTATE '45000' SET MYSQL_ERRNO=30001, MESSAGE_TEXT="Don't remove current user 'root'@'localhost''";
@@ -183,7 +178,7 @@
END IF */|
DELIMITER ;
/*!50701 DROP USER IF EXISTS 'USER'@'%' */;
-CREATE /*M!100103 OR REPLACE */ USER 'USER'@'%' IDENTIFIED VIA unix_socket;
+CREATE /*M!100103 OR REPLACE */ USER 'USER'@'%';
SELECT COALESCE(CURRENT_ROLE(),'NONE') into @current_role;
CREATE ROLE IF NOT EXISTS mariadb_dump_import_role;
GRANT mariadb_dump_import_role TO CURRENT_USER();
@@ -203,7 +198,7 @@
/*!80001 ALTER USER 'root'@'localhost' DEFAULT ROLE NONE */;
GRANT role_1 TO 'USER'@'%';
GRANT role_2 TO 'USER'@'%';
-GRANT USAGE ON *.* TO 'USER'@'%' IDENTIFIED VIA unix_socket;
+GRANT USAGE ON *.* TO 'USER'@'%';
/*M!100005 SET DEFAULT ROLE 'role_2' FOR 'USER'@'%' */;
/*!80001 ALTER USER 'USER'@'%' DEFAULT ROLE 'role_2' */;
GRANT role_2 TO 'role_1' WITH ADMIN OPTION;
@@ -304,9 +299,8 @@
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-INSTALL PLUGIN unix_socket /*M!100401 IF NOT EXISTS */ SONAME 'auth_socket.so';
CREATE USER IF NOT EXISTS 'root'@'localhost';
-CREATE USER IF NOT EXISTS 'USER'@'%' IDENTIFIED VIA unix_socket;
+CREATE USER IF NOT EXISTS 'USER'@'%';
SELECT COALESCE(CURRENT_ROLE(),'NONE') into @current_role;
CREATE ROLE IF NOT EXISTS mariadb_dump_import_role;
GRANT mariadb_dump_import_role TO CURRENT_USER();
@@ -324,7 +318,7 @@
/*!80001 ALTER USER 'root'@'localhost' DEFAULT ROLE NONE */;
GRANT role_1 TO 'USER'@'%';
GRANT role_2 TO 'USER'@'%';
-GRANT USAGE ON *.* TO 'USER'@'%' IDENTIFIED VIA unix_socket;
+GRANT USAGE ON *.* TO 'USER'@'%';
/*M!100005 SET DEFAULT ROLE 'role_2' FOR 'USER'@'%' */;
/*!80001 ALTER USER 'USER'@'%' DEFAULT ROLE 'role_2' */;
GRANT role_2 TO 'role_1' WITH ADMIN OPTION;
@@ -413,12 +407,12 @@
CHECKSUM TABLE mysql.user, mysql.roles_mapping, mysql.time_zone_transition, mysql.plugin,
mysql.servers, mysql.func, mysql.innodb_table_stats, mysql.table_stats;
Table Checksum
-mysql.user 205632094
+mysql.user 926820922
mysql.roles_mapping 3150178430
mysql.time_zone_transition 3895294076
-mysql.plugin 1520695737
+mysql.plugin 0
mysql.servers 2783974349
-mysql.func 3241572444
+mysql.func 310494789
mysql.innodb_table_stats 347867921
mysql.table_stats 664320059
# Opps....
@@ -442,12 +436,12 @@
CHECKSUM TABLE mysql.user, mysql.roles_mapping, mysql.time_zone_transition, mysql.plugin,
mysql.servers, mysql.func, mysql.innodb_table_stats, mysql.table_stats;
Table Checksum
-mysql.user 205632094
+mysql.user 926820922
mysql.roles_mapping 3150178430
mysql.time_zone_transition 3895294076
-mysql.plugin 1520695737
+mysql.plugin 0
mysql.servers 2783974349
-mysql.func 3241572444
+mysql.func 310494789
mysql.innodb_table_stats 347867921
mysql.table_stats 664320059
DROP FUNCTION IF EXISTS metaphon;
@@ -461,7 +455,6 @@
DROP ROLE role_2;
DROP ROLE role_1;
drop user USER;
-uninstall plugin unix_socket;
insert into mysql.user select * from backup_users;
flush privileges;
drop table backup_users;
This diff is collapsed.
--source include/not_embedded.inc
--source include/have_innodb.inc
--source include/have_udf.inc
--source include/platform.inc
--echo #
--echo # MDEV-23630: mysqldump to logically dump system tables
--echo #
--echo #
# might need fixing in 10.4 to different mechanism
create table backup_users like mysql.user;
insert into backup_users select * from mysql.user where host not in ('localhost');
delete from mysql.user where host not in ('localhost');
flush privileges;
create user USER;
if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) NOT IN ('Win32', 'Win64', 'Windows')`)
{
--eval install plugin /*M!100401 IF NOT EXISTS */ unix_socket soname '$AUTH_SOCKET_SO';
alter user USER identified via unix_socket;
}
# time zone data already loaded
CREATE ROLE role_1;
CREATE ROLE role_2 WITH ADMIN role_1;
GRANT SHOW DATABASES ON *.* TO role_1;
GRANT role_1 TO USER;
GRANT role_2 TO USER;
SET DEFAULT ROLE role_2 FOR USER;
ALTER TABLE mysql.roles_mapping ORDER BY Host, User, Role;
# innodb and EITS tables statistics
#
set @save_innodb_stats_persistent= @@innodb_stats_persistent;
create table mysql.tz like mysql.time_zone_transition;
alter table mysql.tz engine=innodb;
insert into mysql.tz select * from mysql.time_zone_transition;
set global innodb_stats_persistent=1;
ANALYZE TABLE mysql.tz PERSISTENT FOR ALL;
# for predictable output in tests
delete from mysql.index_stats where prefix_arity!=1;
delete from mysql.column_stats where column_name!='Time_zone_id';
set time_zone="+03:00";
update mysql.innodb_index_stats set last_update="2020-01-01" where database_name="mysql" and table_name="tz";
update mysql.innodb_table_stats set last_update="2020-01-01" where database_name="mysql" and table_name="tz";
set global innodb_stats_persistent= @save_innodb_stats_persistent;
alter table mysql.time_zone_name ORDER BY Name;
CREATE SERVER s1 FOREIGN DATA WRAPPER mysql OPTIONS(Host 'localhost');
--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO";
#
# Lets actually do some tests.
#
--echo #
--echo # mysqldump of system tables with --system=all
--echo #
--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
--exec $MYSQL_DUMP --skip-comments --system=all
--echo #
--echo # mysqldump of system tables with --system=all --replace
--echo #
--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
--exec $MYSQL_DUMP --skip-comments --system=all --replace
# save this for restore
--exec $MYSQL_DUMP --system=users,servers,stats,timezones,udfs --replace > $MYSQLTEST_VARDIR/tmp/dump1.sql
--echo #
--echo # mysqldump of system tables with --system=all --insert-ignore
--echo #
--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB
--exec $MYSQL_DUMP --skip-comments --system=all --insert-ignore
CHECKSUM TABLE mysql.user, mysql.roles_mapping, mysql.time_zone_transition, mysql.plugin,
mysql.servers, mysql.func, mysql.innodb_table_stats, mysql.table_stats;
--echo # Opps....
CREATE USER mariadb_test_restore IDENTIFIED BY 'getitback';
GRANT ALL ON *.* TO mariadb_test_restore WITH GRANT OPTION;
GRANT PROXY ON ''@'%' TO mariadb_test_restore WITH GRANT OPTION;
GRANT SUPER, CREATE USER /*M!100502 ,FEDERATED ADMIN */ ON *.* TO mariadb_test_restore WITH GRANT OPTION;
drop user USER;
delete from mysql.table_stats;
delete from mysql.innodb_table_stats;
delete from mysql.time_zone_transition;
delete from mysql.time_zone_transition_type;
delete from mysql.time_zone;
delete from mysql.time_zone_name;
delete from mysql.time_zone_leap_second;
DROP FUNCTION IF EXISTS metaphon;
DROP SERVER s1;
set time_zone= @@global.time_zone;
--echo # Restore from mysqldump
--exec $MYSQL --user mariadb_test_restore --password=getitback --show-warnings < $MYSQLTEST_VARDIR/tmp/dump1.sql
#--remove_file $MYSQLTEST_VARDIR/tmp/dump1.sql;
DROP USER mariadb_test_restore;
# successful restore?
CHECKSUM TABLE mysql.user, mysql.roles_mapping, mysql.time_zone_transition, mysql.plugin,
mysql.servers, mysql.func, mysql.innodb_table_stats, mysql.table_stats;
#
# Cleanup
#
DROP FUNCTION IF EXISTS metaphon;
DROP SERVER s1;
# EITS && innodb stats
DELETE FROM mysql.column_stats WHERE db_name='mysql' and table_name in ('tz', 'gtid_slave_pos');
DELETE FROM mysql.index_stats WHERE db_name='mysql' and table_name in ('tz', 'gtid_slave_pos');
DELETE FROM mysql.table_stats WHERE db_name='mysql' and table_name in ('tz', 'gtid_slave_pos');
DELETE FROM mysql.innodb_index_stats WHERE database_name='mysql' and table_name in ('tz','gtid_slave_pos');
DELETE FROM mysql.innodb_table_stats WHERE database_name='mysql' and table_name in ('tz','gtid_slave_pos');
drop table mysql.tz;
DROP ROLE role_2;
DROP ROLE role_1;
drop user USER;
if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) NOT IN ('Win32', 'Win64', 'Windows')`)
{
uninstall plugin unix_socket;
}
insert into mysql.user select * from backup_users;
flush privileges;
drop table backup_users;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment