Yesterday my friend and ex-colleague Sveta published a blog post on how to migrate ownership of stored routines, views and triggers in MySQL.
I usually agree a lot with her and even if I agree with what she wrote, there is one single point I would like to comment: use MySQL Shell !
In the blog post, Sveta recommends the use of mysqldump which I don’t. For any logical dump & load operations, I really recommend the use of MySQL Shell’s Dump & Load Utility ! It’s much faster, it has many nice options like hidden Primary Key creation, and is compatible with OCI.
And of course, MySQL Shell also provides a solution for the problem exposed in the blog post.
Let’s see MySQL Shell in action with the exact same example:
First, using my own user (fred), I create a database and a view:
mysql> create database definers; mysql> use definers; mysql> CREATE VIEW large_tables AS SELECT * FROM information_schema.tables WHERE DATA_LENGTH > 100000000; mysql> SELECT DEFINER, TABLE_SCHEMA, TABLE_NAME FROM information_schema.views WHERE TABLE_NAME='large_tables'; +---------+--------------+--------------+ | DEFINER | TABLE_SCHEMA | TABLE_NAME | +---------+--------------+--------------+ | fred@% | definers | large_tables | +---------+--------------+--------------+
Now, I create the production user, for obvious security reasons, I assign a password to it:
mysql> CREATE USER production identified by '********'; mysql> GRANT ALL ON definers.* TO production@'%'; mysql> GRANT SESSION_VARIABLES_ADMIN ON <em>.</em> TO production@'%';
We can now dump the definers schema using MySQL Shell where I will use fred to connect:
[fred@imac ~] $ mysqlsh fred@localhost MySQL localhost:33060+ 2021-07-08 07:41:47 JS util.dumpSchemas(['definers'], '/tmp/dump') Acquiring global read lock Global read lock acquired Gathering information - done All transactions have been started Locking instance for backup Global read lock has been released Writing global DDL files Running data dump using 4 threads. NOTE: Progress information uses estimated values and may not be accurate. Writing DDL for schema definers Writing DDL for view definers.large_tables ?% (0 rows / ?), 0.00 rows/s, 0.00 B/s uncompressed, 0.00 B/s compressed Duration: 00:00:00s Schemas dumped: 1 Tables dumped: 0 Uncompressed data size: 0 bytes Compressed data size: 0 bytes Compression ratio: 0.0 Rows written: 0 Bytes written: 0 bytes Average uncompressed throughput: 0.00 B/s Average compressed throughput: 0.00 B/s
And now I will load it (the view needs to be removed first if you load it on the same server) using the production user:
[fred@imac ~] $ mysqlsh production@localhost MySQL localhost:33060+ 2021-07-08 07:42:53 JS util.loadDump('/tmp/dump') Loading DDL and Data from '/tmp/dump' using 4 threads. Opening dump… Target is MySQL 8.0.25. Dump was produced from MySQL 8.0.25 Checking for pre-existing objects… Executing common preamble SQL Executing DDL script for schema definers [Worker002] Executing DDL script for definers.large_tables (placeholder for view) Executing DDL script for view definers.large_tables ERROR: Error executing DDL script for view definers.large_tables: MySQL Error 1227 (42000): Access denied; you need (at least one of) the SUPER or SET_USER_ID privilege(s) for this operation: /*!50001 CREATE ALGORITHM=UNDEFINED DEFINER=fred@% SQL SECURITY DEFINER VIEW large_tables AS select information_schema.tables.TABLE_CATALOG AS TABLE_CATALOG,information_schema.tables.TABLE_SCHEMA AS TABLE_SCHEMA,information_schema.tables.TABLE_NAME AS TABLE_NAME,information_schema.tables.TABLE_TYPE AS TABLE_TYPE,information_schema.tables.ENGINE AS ENGINE,information_schema.tables.VERSION AS VERSION,information_schema.tables.ROW_FORMAT AS ROW_FORMAT,information_schema.tables.TABLE_ROWS AS TABLE_ROWS,information_schema.tables.AVG_ROW_LENGTH AS AVG_ROW_LENGTH,information_schema.tables.DATA_LENGTH AS DATA_LENGTH,information_schema.tables.MAX_DATA_LENGTH AS MAX_DATA_LENGTH,information_schema.tables.INDEX_LENGTH AS INDEX_LENGTH,information_schema.tables.DATA_FREE AS DATA_FREE,information_schema.tables.AUTO_INCREMENT AS AUTO_INCREMENT,information_schema.tables.CREATE_TIME AS CREATE_TIME,information_schema.tables.UPDATE_TIME AS UPDATE_TIME,information_schema.tables.CHECK_TIME AS CHECK_TIME,information_schema.tables.TABLE_COLLATION AS TABLE_COLLATION,information_schema.tables.CHECKSUM AS CHECKSUM,information_schema.tables.CREATE_OPTIONS AS CREATE_OPTIONS,information_schema.tables.TABLE_COMMENT AS TABLE_COMMENT from information_schema.TABLES tables where (information_schema.tables.DATA_LENGTH > 100000000) */ <strong>Util.loadDump: Access denied; you need (at least one of) the SUPER or SET_USER_ID privilege(s) for this operation (MYSQLSH 1227)</strong>
As you can see, it failed the exact same way as it happened with mysqldump and this is because by default we don’t enable the strip_definers option.
Now we will do the dump again enabling the option this time:
JS util.dumpSchemas(['definers'], '/tmp/dump', <strong>{compatibility:["strip_definers"]}</strong>) Acquiring global read lock Global read lock acquired Gathering information - done All transactions have been started Locking instance for backup Global read lock has been released Writing global DDL files Running data dump using 4 threads. NOTE: Progress information uses estimated values and may not be accurate. Writing DDL for schema definers Writing DDL for view definers.large_tables NOTE: View definers.large_tables had definer clause removed and SQL SECURITY characteristic set to INVOKER ?% (0 rows / ?), 0.00 rows/s, 0.00 B/s uncompressed, 0.00 B/s compressed Duration: 00:00:00s Schemas dumped: 1 Tables dumped: 0 Uncompressed data size: 0 bytes Compressed data size: 0 bytes Compression ratio: 0.0 Rows written: 0 Bytes written: 0 bytes Average uncompressed throughput: 0.00 B/s Average compressed throughput: 0.00 B/s
And we can see that the dump is now working as expected:
JS util.loadDump('/tmp/dump') Loading DDL and Data from '/tmp/dump' using 4 threads. Opening dump… Target is MySQL 8.0.25. Dump was produced from MySQL 8.0.25 Checking for pre-existing objects… Executing common preamble SQL Executing DDL script for schema definers [Worker002] Executing DDL script for definers.large_tables (placeholder for view) Executing DDL script for view definers.large_tables Executing common postamble SQL No data loaded. 0 warnings were reported during the load.
And if we check the definer this time of the loaded view:
mysql> SELECT DEFINER, TABLE_SCHEMA, TABLE_NAME FROM information_schema.views WHERE TABLE_NAME='large_tables'; +--------------+--------------+--------------+ | DEFINER | TABLE_SCHEMA | TABLE_NAME | +--------------+--------------+--------------+ | production@% | definers | large_tables | +--------------+--------------+--------------+ 1 row in set (0.00 sec)
As you can see, MySQL Shell Dump & Load Utility is the way to go for any logical dump and load: faster and powerful !
Thank you for using MySQL !