[fix](mysqldb) Fix mysqldb upgrade (#25111)

If user has database with same name mysql, will introduce problem when doing checkpoint.

Solution:

Add check for this situation, if duplicate, exit and print log info to prevent damage of metadata;
Add fe config field: mysqldb_replace_name to make things correct if user already has mysql db.
Related pr: #23087 #22868
This commit is contained in:
zhiqqqq
2023-10-08 20:40:56 -05:00
committed by GitHub
parent 9e31cb26bb
commit 7af4be1ee3
6 changed files with 42 additions and 6 deletions

View File

@ -17,9 +17,9 @@
package org.apache.doris.analysis;
import org.apache.doris.catalog.Database;
import org.apache.doris.catalog.DatabaseIf;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.InfoSchemaDb;
import org.apache.doris.catalog.MysqlDb;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
@ -60,9 +60,10 @@ public class DropDbStmt extends DdlStmt {
ErrorReport.reportAnalysisException(ErrorCode.ERR_WRONG_DB_NAME, dbName);
}
dbName = ClusterNamespace.getFullName(getClusterName(), dbName);
// Don't allowed to drop 'information_schema' & 'mysql'
if (dbName.equalsIgnoreCase(ClusterNamespace.getFullName(getClusterName(), InfoSchemaDb.DATABASE_NAME))
|| dbName.equalsIgnoreCase(ClusterNamespace.getFullName(getClusterName(), MysqlDb.DATABASE_NAME))) {
// Don't allow to drop mysql compatible databases
DatabaseIf db = Env.getCurrentInternalCatalog().getDbNullable(dbName);
if (db != null && (db instanceof Database) && ((Database) db).isMysqlCompatibleDatabase()) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_DBACCESS_DENIED_ERROR,
analyzer.getQualifiedUser(), dbName);
}

View File

@ -18,6 +18,7 @@
package org.apache.doris.catalog;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.Config;
/**
* This class is used for MySQL compatibility.
@ -33,7 +34,7 @@ import org.apache.doris.cluster.ClusterNamespace;
* We will add useful system tables in the future.
*/
public class MysqlDb extends MysqlCompatibleDatabase {
public static final String DATABASE_NAME = "mysql";
public static final String DATABASE_NAME = Config.mysqldb_replace_name;
/**
* Database created by user will have database id starting from 10000 {@link Env#NEXT_ID_INIT_VALUE}.
* InfoSchemaDb takes id 0, so we assign id 1 to MysqlDb.

View File

@ -3178,6 +3178,21 @@ public class InternalCatalog implements CatalogIf<Database> {
Database db = new Database();
db.readFields(dis);
newChecksum ^= db.getId();
Database dbPrev = fullNameToDb.get(db.getFullName());
if (dbPrev != null) {
String errMsg;
if (dbPrev.isMysqlCompatibleDatabase() || db.isMysqlCompatibleDatabase()) {
errMsg = String.format(
"Mysql compatibility problem, previous checkpoint already has a database with full name "
+ "%s. If its name is mysql, try to add mysqldb_replace_name=\"mysql_comp\" in fe.conf.",
db.getFullName());
} else {
errMsg = String.format("Logical error, duplicated database fullname: %s, id: %d %d.",
db.getFullName(), db.getId(), fullNameToDb.get(db.getFullName()).getId());
}
throw new IOException(errMsg);
}
idToDb.put(db.getId(), db);
fullNameToDb.put(db.getFullName(), db);
Env.getCurrentGlobalTransactionMgr().addDatabaseTransactionMgr(db.getId());