diff --git a/fe/fe-core/src/main/java/com/starrocks/qe/ConnectProcessor.java b/fe/fe-core/src/main/java/com/starrocks/qe/ConnectProcessor.java index d0c0ff9a81b6d2..a053f6626c485f 100644 --- a/fe/fe-core/src/main/java/com/starrocks/qe/ConnectProcessor.java +++ b/fe/fe-core/src/main/java/com/starrocks/qe/ConnectProcessor.java @@ -580,17 +580,37 @@ private void handleFieldList() throws IOException { ctx.getState().setError("Unknown database(" + ctx.getDatabase() + ")"); return; } - Locker locker = new Locker(); - locker.lockDatabase(db.getId(), LockType.READ); + // Internal catalog: lookup resolves to Database.nameToTable (a ConcurrentHashMap, + // lock-free safe). External catalog: lookup routes through ConnectorMetadata, whose + // concurrency is connector-managed. No FE write path takes the LockManager lock on + // external db ids, so the intensive lock acquired below is harmless overhead on + // external catalogs and the unlocked lookup changes nothing for them. + Table table; try { - // we should get table through metadata manager - Table table = ctx.getGlobalStateMgr().getMetadataMgr().getTable( + table = ctx.getGlobalStateMgr().getMetadataMgr().getTable( ctx, ctx.getCurrentCatalog(), ctx.getDatabase(), tableName); - if (table == null) { + } catch (StarRocksConnectorException e) { + LOG.error("errors happened when getting table {}", tableName, e); + ctx.getState().setEof(); + return; + } + if (table == null) { + ctx.getState().setError("Unknown table(" + tableName + ")"); + return; + } + + Locker locker = new Locker(); + locker.lockTableWithIntensiveDbLock(db.getId(), table.getId(), LockType.READ); + try { + // Revalidate by name to detect concurrent DROP/RENAME between unlocked lookup + // and lock acquisition. The table id is stable, so id-based revalidation would + // miss a RENAME that re-binds the name to a different table. Internal-catalog + // only: LocalMetastore doesn't track connector tables, so a re-fetch for + // external catalogs would always return null and falsely fail. + if (db.getCatalogName() == null && db.getTable(tableName) != table) { ctx.getState().setError("Unknown table(" + tableName + ")"); return; } - MysqlSerializer serializer = ctx.getSerializer(); MysqlChannel channel = ctx.getMysqlChannel(); @@ -605,7 +625,7 @@ private void handleFieldList() throws IOException { } catch (StarRocksConnectorException e) { LOG.error("errors happened when getting table {}", tableName, e); } finally { - locker.unLockDatabase(db.getId(), LockType.READ); + locker.unLockTableWithIntensiveDbLock(db.getId(), table.getId(), LockType.READ); } ctx.getState().setEof(); } diff --git a/fe/fe-core/src/main/java/com/starrocks/qe/ShowExecutor.java b/fe/fe-core/src/main/java/com/starrocks/qe/ShowExecutor.java index 9a1deadd65fd79..e902912fdad1c2 100644 --- a/fe/fe-core/src/main/java/com/starrocks/qe/ShowExecutor.java +++ b/fe/fe-core/src/main/java/com/starrocks/qe/ShowExecutor.java @@ -743,14 +743,15 @@ private ShowResultSet showCreateInternalCatalogTable(ShowCreateTableStmt showStm Database db = GlobalStateMgr.getCurrentState().getLocalMetastore().getDb(showStmt.getDb()); MetaUtils.checkDbNullAndReport(db, showStmt.getDb()); List> rows = Lists.newArrayList(); - Locker locker = new Locker(); - locker.lockDatabase(db.getId(), LockType.READ); - try { - Table table = MetaUtils.getSessionAwareTable(connectContext, db, showStmt.getTbl()); - if (table == null) { - if (showStmt.getType() != ShowCreateTableStmt.CreateTableType.MATERIALIZED_VIEW) { - ErrorReport.reportSemanticException(ErrorCode.ERR_BAD_TABLE_ERROR, showStmt.getTable()); - } else { + TableName tableName = showStmt.getTbl(); + Table table = MetaUtils.getSessionAwareTable(connectContext, db, tableName); + if (table == null) { + if (showStmt.getType() != ShowCreateTableStmt.CreateTableType.MATERIALIZED_VIEW) { + ErrorReport.reportSemanticException(ErrorCode.ERR_BAD_TABLE_ERROR, showStmt.getTable()); + } else { + Locker dbLocker = new Locker(); + dbLocker.lockDatabase(db.getId(), LockType.READ); + try { // For Sync Materialized View, it is a mv index inside OLAP table, // so we can not get it from database. for (Table tbl : GlobalStateMgr.getCurrentState().getLocalMetastore().getTables(db.getId())) { @@ -764,7 +765,7 @@ private ShowResultSet showCreateInternalCatalogTable(ShowCreateTableStmt showStm String mvName = olapTable.getIndexNameById(mvMeta.getIndexId()); rows.add(Lists.newArrayList(showStmt.getTable(), ShowMaterializedViewStatus.buildCreateMVSql(olapTable, - mvName, mvMeta), "utf8", "utf8_general_ci")); + mvName, mvMeta), "utf8", "utf8_general_ci")); } else { rows.add(Lists.newArrayList(showStmt.getTable(), mvMeta.getOriginStmt(), "utf8", "utf8_general_ci")); @@ -772,17 +773,26 @@ private ShowResultSet showCreateInternalCatalogTable(ShowCreateTableStmt showStm ShowResultSetMetaData showResultSetMetaData = ShowResultSetMetaData.builder() .addColumn(new Column("Materialized View", ScalarType.createVarchar(20))) - .addColumn(new Column("Create Materialized View", ScalarType.createVarchar(30))) + .addColumn(new Column("Create Materialized View", + ScalarType.createVarchar(30))) .build(); return new ShowResultSet(showResultSetMetaData, rows); } } } } - ErrorReport.reportSemanticException(ErrorCode.ERR_BAD_TABLE_ERROR, showStmt.getTable()); + } finally { + dbLocker.unLockDatabase(db.getId(), LockType.READ); } + ErrorReport.reportSemanticException(ErrorCode.ERR_BAD_TABLE_ERROR, showStmt.getTable()); + } + } + Locker locker = new Locker(); + locker.lockTableWithIntensiveDbLock(db.getId(), table.getId(), LockType.READ); + try { + if (MetaUtils.getSessionAwareTable(connectContext, db, tableName) != table) { + ErrorReport.reportSemanticException(ErrorCode.ERR_BAD_TABLE_ERROR, showStmt.getTable()); } - List createTableStmt = Lists.newArrayList(); AstToStringBuilder.getDdlStmt(table, createTableStmt, null, null, false, true /* hide password */); if (createTableStmt.isEmpty()) { @@ -835,7 +845,7 @@ private ShowResultSet showCreateInternalCatalogTable(ShowCreateTableStmt showStm return new ShowResultSet(showResultMetaFactory.getMetadata(showStmt), rows); } } finally { - locker.unLockDatabase(db.getId(), LockType.READ); + locker.unLockTableWithIntensiveDbLock(db.getId(), table.getId(), LockType.READ); } } @@ -1713,7 +1723,7 @@ public ShowResultSet visitShowTabletStatement(ShowTabletStmt statement, ConnectC dbName = db.getFullName(); Locker locker = new Locker(); - locker.lockDatabase(db.getId(), LockType.READ); + locker.lockTableWithIntensiveDbLock(db.getId(), tableId, LockType.READ); try { Table table = GlobalStateMgr.getCurrentState().getLocalMetastore().getTable(db.getId(), tableId); if (!(table instanceof OlapTable)) { @@ -1774,7 +1784,7 @@ public ShowResultSet visitShowTabletStatement(ShowTabletStmt statement, ConnectC } } finally { - locker.unLockDatabase(db.getId(), LockType.READ); + locker.unLockTableWithIntensiveDbLock(db.getId(), tableId, LockType.READ); } } while (false); @@ -1788,18 +1798,19 @@ public ShowResultSet visitShowTabletStatement(ShowTabletStmt statement, ConnectC Database db = globalStateMgr.getLocalMetastore().getDb(statement.getDbName()); MetaUtils.checkDbNullAndReport(db, statement.getDbName()); + TableName tableName = new TableName(statement.getDbName(), statement.getTableName()); + Table table = MetaUtils.getSessionAwareTable(context, db, tableName); + if (!table.isNativeTableOrMaterializedView()) { + ErrorReport.reportSemanticException(ErrorCode.ERR_NOT_OLAP_TABLE, statement.getTableName()); + } + Locker locker = new Locker(); - locker.lockDatabase(db.getId(), LockType.READ); + locker.lockTableWithIntensiveDbLock(db.getId(), table.getId(), LockType.READ); try { - Table table = MetaUtils.getSessionAwareTable( - context, db, new TableName(statement.getDbName(), statement.getTableName())); - if (table == null) { - ErrorReport.reportSemanticException(ErrorCode.ERR_BAD_TABLE_ERROR, statement.getTableName()); - } - if (!table.isNativeTableOrMaterializedView()) { - ErrorReport.reportSemanticException(ErrorCode.ERR_NOT_OLAP_TABLE, statement.getTableName()); + if (MetaUtils.getSessionAwareTable(context, db, tableName) != table) { + ErrorReport.reportSemanticException(ErrorCode.ERR_BAD_TABLE_ERROR, + statement.getTableName()); } - Pair privResult = Authorizer.checkPrivForShowTablet( context, db.getFullName(), table); if (!privResult.first) { @@ -1894,7 +1905,7 @@ public ShowResultSet visitShowTabletStatement(ShowTabletStmt statement, ConnectC rows.add(oneTablet); } } finally { - locker.unLockDatabase(db.getId(), LockType.READ); + locker.unLockTableWithIntensiveDbLock(db.getId(), table.getId(), LockType.READ); } }