UI超时后通过PHP后端终止Snowflake运行中查询的实现方案
解决UI超时后终止Snowflake运行中查询的PHP实现方案
核心思路
要精准终止仅由UI发起且超时未完成的查询,关键是给这类查询打上专属标识,后续通过标识定位并终止目标查询,避免影响其他正常运行的任务。
具体实现步骤
1. 给UI发起的查询添加专属标识
当UI请求后端执行查询时,生成一个唯一标识(结合会话ID和随机串保证唯一性),将其嵌入查询语句的注释中作为自定义标签,同时把标识和Snowflake返回的STATEMENT_ID关联存储(推荐用Redis,也可用临时数据库表)。
示例代码:
// 生成唯一查询标识,绑定到当前用户会话 $queryTag = 'UI_SESSION_' . session_id() . '_' . uniqid(); $_SESSION['pending_query_tag'] = $queryTag; // 执行Snowflake查询,嵌入标识标签 $stmt = $snowflakeConn->prepare(" SELECT * FROM your_large_table /* UI_QUERY_TAG: {$queryTag} */ "); $stmt->execute(); // 获取查询的STATEMENT_ID,存入Redis(设置过期时间略长于UI超时) $statementId = $stmt->getStatementId(); $redis->setex("ui_query:{$queryTag}", 180, $statementId);
2. UI超时后触发终止逻辑
UI超时后,前端主动调用后端的终止接口,后端通过会话中存储的标识,从Redis取出对应的STATEMENT_ID,调用Snowflake的终止语句函数。
终止接口示例:
// 前端超时后调用此接口 if (isset($_SESSION['pending_query_tag'])) { $queryTag = $_SESSION['pending_query_tag']; $statementId = $redis->get("ui_query:{$queryTag}"); if ($statementId) { // 执行Snowflake终止命令 $snowflakeConn->query("SELECT SYSTEM$CANCEL_STATEMENT('{$statementId}')"); // 清理缓存和会话数据 $redis->del("ui_query:{$queryTag}"); unset($_SESSION['pending_query_tag']); } }
3. 备选方案:通过Snowflake信息架构定位查询
如果无法提前获取STATEMENT_ID,可通过查询Snowflake的QUERY_HISTORY视图,筛选出带专属标签的运行中查询并终止:
$queryTag = $_SESSION['pending_query_tag']; $result = $snowflakeConn->query(" SELECT STATEMENT_ID FROM TABLE(INFORMATION_SCHEMA.QUERY_HISTORY(SESSION_ID => CURRENT_SESSION())) WHERE STATUS = 'RUNNING' AND QUERY_TEXT LIKE '%/* UI_QUERY_TAG: {$queryTag} */%' "); while ($row = $result->fetch_assoc()) { $snowflakeConn->query("SELECT SYSTEM$CANCEL_STATEMENT('{$row['STATEMENT_ID']}')"); }
注意事项
- 确保Snowflake账户拥有
MONITOR或更高权限,才能执行SYSTEM$CANCEL_STATEMENT和查询QUERY_HISTORY。 - Redis的过期时间建议设为UI超时时间的2-3倍,避免因网络延迟导致记录提前失效。
- 若用户会话过期,可通过定时任务扫描Redis中过期的查询记录,批量终止残留的运行中查询。
内容的提问来源于stack exchange,提问作者Mukul Kumar
相关产品推荐
相关产品推荐

