From: Date: August 22 2003 12:27am Subject: Re: new mysqldump features (patch) List-Archive: http://lists.mysql.com/internals/9731 Message-Id: <20030821222708.GB94308@serg.mylan> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Hi! On Aug 20, John David Duncan wrote: > Hi, Thanks for the patch! The features look useful indeed! See my comments below... > In the attached patch I have implemented two new options in mysqldump. > The -R (--rename-tables) option loads all tables using temporary names > and then renames them while holding a lock. This can be useful when it is > necessary to minimize lock time. The output looks like this: > > sh% mysqldump --rename-tables mydb zip city > > CREATE TABLE _new_zip ... > CREATE TABLE _new_city ... > INSERT ... > > LOCK TABLES zip city WRITE; > DROP TABLE zip; > ALTER TABLE _new_zip RENAME zip; > DROP TABLE city; > ALTER TABLE _new_city RENAME city; > UNLOCK TABLES; I would agree with Tim here - it would be faster, simpler, and "more atomic" to use RENAME TABLE here. In your example it would be RENAME TABLE zip TO _old_zip, _new_zip TO zip, city TO _old_city, _new_city TO city; Also, I would agree that it's better to rename the option, as Tim suggested. And to add --atomic-prefix (or whatever the name is). > The -U (--with-use-db) option assures that "USE db_name;" is always in the > output; this is otherwise not true unless --databases or --all-databases > is used. Why do you think this option is necessary ? I'm sure you need it, so you have a working scenario where this option helps. Can you describe it briefly ? > @@ -579,6 +606,9 @@ > > sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d", (opt_quoted || opt_keywords)); > table_name=quote_name(table,table_buff); > + if(opt_rename_tables) > + target_table=rename_and_quote(table,target_buff); > + else target_table=table_name; > if (!mysql_query(sock,insert_pat)) > { > /* using SHOW CREATE statement */ > @@ -610,14 +640,26 @@ > write_header(sql_file, db); > } > if (!opt_xml) > - fprintf(sql_file, "\n--\n-- Table structure for table '%s'\n--\n\n", > - table); > + fprintf(sql_file, "\n--\n-- Table structure for table '%s'\n--\n\n",table); > if (opt_drop) > - fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",table_name); > + fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",target_table); > > tableRes=mysql_store_result(sock); > row=mysql_fetch_row(tableRes); > - if (!opt_xml) > + if(opt_rename_tables) { > + char *s = row[1]; > + if(!(bcmp(row[1],"CREATE TABLE ",13))) { Pardon me ? When this condition may ever fail ? > + fprintf(sql_file,"CREATE TABLE %s ",target_table); > + for(s+=13 ; *s++ != ' ' ; ); This is wrong, you cannot assume that table name won't contain spaces. > + fprintf(sql_file, "%s;\n", s); > + } > + else { > + fprintf(sql_file,"-- Failed to use renamed table\n\n"); > + target_table=table_name; > + opt_rename_tables=0; > + } > + } > + else if (!opt_xml) > fprintf(sql_file, "%s;\n", row[1]); > mysql_free_result(tableRes); > } > @@ -690,14 +732,14 @@ > fprintf(sql_file, "\n--\n-- Table structure for table '%s'\n--\n\n", > table); > if (opt_drop) > - fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",table_name); > - fprintf(sql_file, "CREATE TABLE %s (\n", table_name); > + fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",target_table); > + fprintf(sql_file, "CREATE TABLE %s (\n", target_table); this is questionable. I don't really know what to do when opt_drop is used together with your opt_rename_tables. Should it (opt_drop) apply to target_table or original table_name ? > } > if (cFlag) > - sprintf(insert_pat, "INSERT %sINTO %s (", delayed, table_name); > + sprintf(insert_pat, "INSERT %sINTO %s (", delayed, target_table); > else > { > - sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, table_name); > + sprintf(insert_pat, "INSERT %sINTO %s VALUES ", delayed, target_table); > if (!extended_insert) > strcat(insert_pat,"("); > } > static void dumpTable(uint numFields, char *table) > { > - char query[QUERY_LENGTH], *end, buff[256],table_buff[NAME_LEN+3]; > + char query[QUERY_LENGTH], *end, *target_table; > + char buff[256],table_buff[NAME_LEN+3],target_buff[NAME_LEN+3]; > MYSQL_RES *res; > MYSQL_FIELD *field; > MYSQL_ROW row; > @@ -909,6 +952,9 @@ > > if (verbose) > fprintf(stderr, "-- Sending SELECT query...\n"); > + if(opt_rename_tables) > + target_table=rename_and_quote(table,target_buff); > + else target_table=quote_name(table,table_buff); Why do it several times ? Isn't it better to pass it as a parameter ? > if (path) > { > char filename[FN_REFLEN], tmp_path[FN_REFLEN]; > @@ -1299,7 +1345,7 @@ > DBerror(sock, "when doing refresh"); > /* We shall continue here, if --force was given */ > } > - while ((table = getTableName(0))) > + while ((table = getTableName(1))) This way you removed mysql_free_result() call. Better to do things clean. That is to have getTableName(opt_rename_tables) here and getTableName(0) in rename_all_in_db(). > { > numrows = getTableStructure(table, database); > if (!dFlag && numrows > 0) > @@ -1309,6 +1355,8 @@ > fprintf(md_result_file, "\n"); > if (lock_tables) > mysql_query(sock,"UNLOCK_TABLES"); > + if (opt_rename_tables) > + rename_all_in_db(database); > return 0; > } /* dump_all_tables_in_db */ Besides these minor comments, the patch is very good! Regards, Sergei -- __ ___ ___ ____ __ / |/ /_ __/ __/ __ \/ / Sergei Golubchik / /|_/ / // /\ \/ /_/ / /__ MySQL AB, Senior Software Developer /_/ /_/\_, /___/\___\_\___/ Osnabrueck, Germany <___/ www.mysql.com