关于 PreparedStatement

news2024/9/20 11:01:26

Mysql 层面的语法也支持 prepare
这个确实第一次见

  • PREPARE prepares a statement for execution (see Section 13.5.1, “PREPARE Statement”).
  • EXECUTE executes a prepared statement (see Section 13.5.2, “EXECUTE Statement”).
  • DEALLOCATE PREPARE releases a prepared statement (see Section 13.5.3, “DEALLOCATE PREPARE Statement”).
mysql> PREPARE stmt1 FROM 'SELECT * FROM words where id = ?';
Query OK, 0 rows affected (0.00 sec)
Statement prepared

mysql> SET @i=1;
Query OK, 0 rows affected (0.00 sec)
mysql> EXECUTE stmt1 USING @i;
Empty set (0.01 sec)

mysql> SET @i=2;
Query OK, 0 rows affected (0.00 sec)
mysql> EXECUTE stmt1 USING @i;
+----+------+
| id | word |
+----+------+
|  2 | 123  |
+----+------+
1 row in set (0.00 sec)

mysql> deallocate prepare stmt1;
Query OK, 0 rows affected (0.00 sec)

mysql> EXECUTE stmt1 USING @i;
ERROR 1243 (HY000): Unknown prepared statement handler (stmt1) given to EXECUTE

useServerPrepStmts=true

useServerPrepStmts

Use server-side prepared statements if the server supports them?

Default: false

Since version: 3.1.0

如果我们没有在 jdbc 参数中声明这个参数、即使我们在代码中使用了 PreparedStatement 实际上是毫无作用的

    try (PreparedStatement psts = conn.prepareStatement("delete from words where id = ?")) {
      psts.setInt(1, 1);
      psts.execute();
      stopwatch.stop();
      System.out.println("stopwatch = " + stopwatch.elapsed(TimeUnit.MILLISECONDS));
      psts.setInt(1, 10);
      psts.execute();
    } 

抓包看看

在这里插入图片描述

mysql general log:

2020-05-04T13:06:07.883131Z	   15 Connect	root@localhost on test using TCP/IP
2020-05-04T13:06:07.885668Z	   15 Query	/* mysql-connector-java-8.0.16 (Revision: 34cbc6bc61f72836e26327537a432d6db7c77de6) */SELECT  @@session.auto_increment_increment AS auto_increment_increment, @@character_set_client AS character_set_client, @@character_set_connection AS character_set_connection, @@character_set_results AS character_set_results, @@character_set_server AS character_set_server, @@collation_server AS collation_server, @@collation_connection AS collation_connection, @@init_connect AS init_connect, @@interactive_timeout AS interactive_timeout, @@license AS license, @@lower_case_table_names AS lower_case_table_names, @@max_allowed_packet AS max_allowed_packet, @@net_write_timeout AS net_write_timeout, @@performance_schema AS performance_schema, @@sql_mode AS sql_mode, @@system_time_zone AS system_time_zone, @@time_zone AS time_zone, @@transaction_isolation AS transaction_isolation, @@wait_timeout AS wait_timeout
2020-05-04T13:06:07.905021Z	   15 Query	SET character_set_results = NULL
2020-05-04T13:06:07.929557Z	   15 Query	delete from words where id = 1
2020-05-04T13:06:07.934906Z	   15 Query	delete from words where id = 10
2020-05-04T13:06:07.940645Z	   15 Quit

当我们使用 useServerPrepStmts=true 之后

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

log

2020-05-04T13:15:55.611149Z	   16 Connect	root@localhost on test using TCP/IP
2020-05-04T13:15:55.615655Z	   16 Query	/* mysql-connector-java-8.0.16 (Revision: 34cbc6bc61f72836e26327537a432d6db7c77de6) */SELECT  @@session.auto_increment_increment AS auto_increment_increment, @@character_set_client AS character_set_client, @@character_set_connection AS character_set_connection, @@character_set_results AS character_set_results, @@character_set_server AS character_set_server, @@collation_server AS collation_server, @@collation_connection AS collation_connection, @@init_connect AS init_connect, @@interactive_timeout AS interactive_timeout, @@license AS license, @@lower_case_table_names AS lower_case_table_names, @@max_allowed_packet AS max_allowed_packet, @@net_write_timeout AS net_write_timeout, @@performance_schema AS performance_schema, @@sql_mode AS sql_mode, @@system_time_zone AS system_time_zone, @@time_zone AS time_zone, @@transaction_isolation AS transaction_isolation, @@wait_timeout AS wait_timeout
2020-05-04T13:15:55.640086Z	   16 Query	SET character_set_results = NULL
2020-05-04T13:15:55.672345Z	   16 Prepare	delete from words where id = ?
2020-05-04T13:15:55.676355Z	   16 Execute	delete from words where id = 1
2020-05-04T13:15:55.681600Z	   16 Execute	delete from words where id = 10
2020-05-04T13:15:55.681949Z	   16 Close stmt
2020-05-04T13:15:55.687659Z	   16 Quit

cachePrepStmts

客户端 connection 级别缓存预编译的 sql

@Test
@SneakyThrows
public void testPreCompile() {
  String connectString = "jdbc:mysql://localhost/test?user=root&password=toor&useLocalSessionState=true&useSSL=false&useServerPrepStmts=true&cachePrepStmts=true";
  Class.forName("com.mysql.jdbc.Driver")
    .newInstance();
  try (Connection conn = DriverManager.getConnection(connectString)) {
    Stopwatch stopwatch = Stopwatch.createStarted();
    try (PreparedStatement psts = conn.prepareStatement("delete from words where id = ?")) {
      psts.setInt(1, 1);
      psts.execute();
      stopwatch.stop();
      System.out.println("stopwatch = " + stopwatch.elapsed(TimeUnit.MILLISECONDS));
      psts.setInt(1, 10);
      psts.execute();
    }

    // 上面的stmt关闭之后,再次执行
    try (PreparedStatement psts = conn.prepareStatement("delete from words where id = ?")) {
      psts.setInt(1, 100);
      psts.execute();
    }
  }

  // 上面的connection关闭之后,再次执行
  try (Connection conn = DriverManager.getConnection(connectString)) {
    try (PreparedStatement psts = conn.prepareStatement("delete from words where id = ?")) {
      psts.setInt(1, 66);
      psts.execute();
    }
  }

}

在这里插入图片描述

2020-05-04T15:17:32.921041Z	   19 Connect	root@localhost on test using TCP/IP
2020-05-04T15:17:32.929561Z	   19 Query	/* mysql-connector-java-8.0.16 (Revision: 34cbc6bc61f72836e26327537a432d6db7c77de6) */SELECT  @@session.auto_increment_increment AS auto_increment_increment, @@character_set_client AS character_set_client, @@character_set_connection AS character_set_connection, @@character_set_results AS character_set_results, @@character_set_server AS character_set_server, @@collation_server AS collation_server, @@collation_connection AS collation_connection, @@init_connect AS init_connect, @@interactive_timeout AS interactive_timeout, @@license AS license, @@lower_case_table_names AS lower_case_table_names, @@max_allowed_packet AS max_allowed_packet, @@net_write_timeout AS net_write_timeout, @@performance_schema AS performance_schema, @@sql_mode AS sql_mode, @@system_time_zone AS system_time_zone, @@time_zone AS time_zone, @@transaction_isolation AS transaction_isolation, @@wait_timeout AS wait_timeout
2020-05-04T15:17:32.949986Z	   19 Query	SET character_set_results = NULL
2020-05-04T15:17:32.983173Z	   19 Prepare	delete from words where id = ?
2020-05-04T15:17:32.990498Z	   19 Execute	delete from words where id = 1
2020-05-04T15:17:32.997115Z	   19 Execute	delete from words where id = 10
2020-05-04T15:17:32.997566Z	   19 Reset stmt
2020-05-04T15:17:32.997725Z	   19 Execute	delete from words where id = 100
2020-05-04T15:17:33.003682Z	   19 Quit
2020-05-04T15:17:33.009206Z	   20 Connect	root@localhost on test using TCP/IP
2020-05-04T15:17:33.009643Z	   20 Query	/* mysql-connector-java-8.0.16 (Revision: 34cbc6bc61f72836e26327537a432d6db7c77de6) */SELECT  @@session.auto_increment_increment AS auto_increment_increment, @@character_set_client AS character_set_client, @@character_set_connection AS character_set_connection, @@character_set_results AS character_set_results, @@character_set_server AS character_set_server, @@collation_server AS collation_server, @@collation_connection AS collation_connection, @@init_connect AS init_connect, @@interactive_timeout AS interactive_timeout, @@license AS license, @@lower_case_table_names AS lower_case_table_names, @@max_allowed_packet AS max_allowed_packet, @@net_write_timeout AS net_write_timeout, @@performance_schema AS performance_schema, @@sql_mode AS sql_mode, @@system_time_zone AS system_time_zone, @@time_zone AS time_zone, @@transaction_isolation AS transaction_isolation, @@wait_timeout AS wait_timeout
2020-05-04T15:17:33.010569Z	   20 Query	SET character_set_results = NULL
2020-05-04T15:17:33.011244Z	   20 Prepare	delete from words where id = ?
2020-05-04T15:17:33.011475Z	   20 Execute	delete from words where id = 66
2020-05-04T15:17:33.114892Z	   20 Quit

我们直接来看看它是怎么存储的

在这里插入图片描述

在这里插入图片描述

既然是缓存、肯定涉及到缓存的个数以及单个缓存值的大小

prepStmtCacheSize & prepStmtCacheSqlLimit

prepStmtCacheSize 默认值为 25 注意这里是一个 connection 下最多缓存 25 个预编译的 Statement

prepStmtCacheSqlLimit 默认是 256 单纯就是 sql 的长度

在这里插入图片描述

源码

在这里插入图片描述

com.mysql.cj.jdbc.ConnectionImpl#prepareStatement(java.lang.String, int, int)

    @Override
    public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        synchronized (getConnectionMutex()) {
            checkClosed();

            //
            // FIXME: Create warnings if can't create results of the given type or concurrency
            //
            ClientPreparedStatement pStmt = null;

            boolean canServerPrepare = true;

            String nativeSql = this.processEscapeCodesForPrepStmts.getValue() ? nativeSQL(sql) : sql;
			// useServerPrepStmts 属性
            if (this.useServerPrepStmts.getValue() && this.emulateUnsupportedPstmts.getValue()) {
                canServerPrepare = canHandleAsServerPreparedStatement(nativeSql);
            }

            if (this.useServerPrepStmts.getValue() && canServerPrepare) {
				// cachePrepStmts 缓存预编译 Statement
                if (this.cachePrepStmts.getValue()) {
                    synchronized (this.serverSideStatementCache) {
						// 从缓存中获取
                        pStmt = this.serverSideStatementCache.remove(new CompoundCacheKey(this.database, sql));

                        if (pStmt != null) {
							// 强转为ServerPreparedStatement,清理参数,直接返回
                            ((com.mysql.cj.jdbc.ServerPreparedStatement) pStmt).setClosed(false);
                            pStmt.clearParameters();
                        }

                        if (pStmt == null) {
                            try {
                                pStmt = ServerPreparedStatement.getInstance(getMultiHostSafeProxy(), nativeSql, this.database, resultSetType,
                                        resultSetConcurrency);
                                if (sql.length() < this.prepStmtCacheSqlLimit.getValue()) {
                                    ((com.mysql.cj.jdbc.ServerPreparedStatement) pStmt).isCacheable = true;
                                }

                                pStmt.setResultSetType(resultSetType);
                                pStmt.setResultSetConcurrency(resultSetConcurrency);
                            } catch (SQLException sqlEx) {
                                // Punt, if necessary
                                if (this.emulateUnsupportedPstmts.getValue()) {
                                    pStmt = (ClientPreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);

                                    if (sql.length() < this.prepStmtCacheSqlLimit.getValue()) {
                                        this.serverSideStatementCheckCache.put(sql, Boolean.FALSE);
                                    }
                                } else {
                                    throw sqlEx;
                                }
                            }
                        }
                    }
                } else {
                    try {
                        pStmt = ServerPreparedStatement.getInstance(getMultiHostSafeProxy(), nativeSql, this.database, resultSetType, resultSetConcurrency);

                        pStmt.setResultSetType(resultSetType);
                        pStmt.setResultSetConcurrency(resultSetConcurrency);
                    } catch (SQLException sqlEx) {
                        // Punt, if necessary
                        if (this.emulateUnsupportedPstmts.getValue()) {
                            pStmt = (ClientPreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
                        } else {
                            throw sqlEx;
                        }
                    }
                }
            } else {
                pStmt = (ClientPreparedStatement) clientPrepareStatement(nativeSql, resultSetType, resultSetConcurrency, false);
            }

            return pStmt;
        }
    }

close 的时候会重新放回去缓存

// com.mysql.cj.jdbc.ServerPreparedStatement#close
 @Override
public void close() throws SQLException {
  JdbcConnection locallyScopedConn = this.connection;

  if (locallyScopedConn == null) {
    return; // already closed
  }

  synchronized (locallyScopedConn.getConnectionMutex()) {

    if (this.isCached && isPoolable() && !this.isClosed) {
      clearParameters();

      this.isClosed = true;
			// 重新缓存起来
      this.connection.recachePreparedStatement(this);
      return;
    }

    this.isClosed = false;
    realClose(true, true);
  }
}

// com.mysql.cj.jdbc.ConnectionImpl#recachePreparedStatement
    @Override
    public void recachePreparedStatement(JdbcPreparedStatement pstmt) throws SQLException {
        synchronized (getConnectionMutex()) {
            if (this.cachePrepStmts.getValue() && pstmt.isPoolable()) {
                synchronized (this.serverSideStatementCache) {
                    Object oldServerPrepStmt = this.serverSideStatementCache.put(
                            new CompoundCacheKey(pstmt.getCurrentCatalog(), ((PreparedQuery<?>) pstmt.getQuery()).getOriginalSql()),
                            (ServerPreparedStatement) pstmt);
                    if (oldServerPrepStmt != null && oldServerPrepStmt != pstmt) {
                        ((ServerPreparedStatement) oldServerPrepStmt).isCached = false;
                        ((ServerPreparedStatement) oldServerPrepStmt).setClosed(false);
                        ((ServerPreparedStatement) oldServerPrepStmt).realClose(true, true);
                    }
                }
            }
        }
    }

关于 PSCache

这个是关于 druid 的

争议较大的是 mysql 的时候是否开启 PSCache、下面 github 的 issue 是处于 open 状态

// com.alibaba.druid.pool.DruidPooledConnection#closePoolableStatement
public void closePoolableStatement(DruidPooledPreparedStatement stmt) throws SQLException {
  PreparedStatement rawStatement = stmt.getRawPreparedStatement();

  if (holder == null) {
    return;
  }

  if (stmt.isPooled()) {
    try {
      rawStatement.clearParameters();
    } catch (SQLException ex) {
      this.handleException(ex, null);
      if (rawStatement.getConnection().isClosed()) {
        return;
      }

      LOG.error("clear parameter error", ex);
    }
  }

  PreparedStatementHolder stmtHolder = stmt.getPreparedStatementHolder();
  stmtHolder.decrementInUseCount();
  // holder.isPoolPreparedStatements 对应上面配置的开关
  if (stmt.isPooled() && holder.isPoolPreparedStatements() && stmt.exceptionCount == 0) {
    // 放入缓存池子中
    holder.getStatementPool().put(stmtHolder);

    stmt.clearResultSet();
    holder.removeTrace(stmt);

    stmtHolder.setFetchRowPeak(stmt.getFetchRowPeak());
		
    stmt.setClosed(true); // soft set close
  } else if (stmt.isPooled() && holder.isPoolPreparedStatements()) {
    // the PreparedStatement threw an exception
    stmt.clearResultSet();
    holder.removeTrace(stmt);

    // 开启了PSCache但是这个stmt抛出过异常,直接从缓存中移除
    holder.getStatementPool()
      .remove(stmtHolder);
  } else {
    try {
      //Connection behind the statement may be in invalid state, which will throw a SQLException.
      //In this case, the exception is desired to be properly handled to remove the unusable connection from the pool.
      stmt.closeInternal();
    } catch (SQLException ex) {
      this.handleException(ex, null);
      throw ex;
    } finally {
      holder.getDataSource().incrementClosedPreparedStatementCount();
    }
  }
}

https://qsli.github.io/2020/05/05/cache-prep-stmts/

https://github.com/alibaba/druid/issues/2273

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2124429.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

半天玩转大模型技术之RAG

引 言 当前大模型在金融行业最广泛的应用之一就是知识问答&#xff0c;而支撑该应用的技术正是当下火热的检索增强生成&#xff08;Retrieval Augmented Generation&#xff09;技术&#xff0c;简称 RAG。因企业具体的业务往往需要注入特定的知识&#xff0c;比如ChatBI中企业…

Google出了一个黑科技,可以把书变成真人多角色对话的音频,效果真的很牛!

大家有没有想过,像读书、查资料这种事情,如果可以用听的,效率会不会更高?我想大部分人都曾有过这种念头。尤其是在这信息爆炸的时代,手头上有大量的书籍、论文等资源,但我们根本没时间一页一页地去翻。对吧?这时,Google Illuminate 的出现,简直像是为我们解了燃眉之急…

力扣: 赎金信

文章目录 需求分析及编码结尾 需求 给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以&#xff0c;返回 true &#xff1b;否则返回 false 。 magazine 中的每个字符只能在 ransomNote 中使用一次…

kubernetes中的微服务Service(ClusterIP、NodePort、LoadBalancer)

目录 一 、什么是微服务 二 、微服务的类型 三、 ipvs模式 3.1 ipvs模式配置方式 四、微服务类型详解 4.1 clusterip 4.2 ClusterIP中的特殊模式headless 4.3 nodeport 4.4 loadbalancer 4.5 metalLB 4.6 externalname 五 Ingress-nginx 5.1 ingress-nginx功能 5.2…

【大模型专栏—入门篇】CUDA入门与AutoDL“炼丹”

大模型专栏介绍 &#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本文为大模型专栏子篇&#xff0c;大模型专栏将持续更新&#xff0c;主要讲解大模型从入门到实战打怪升级。如有兴趣&#xff0c;欢迎您的阅读。 &#x1f4…

PointNet++改进策略 :模块改进 | SWA| PVT,融入Transformer的点云与体素的模块同时提升模型精度和效率

目录 介绍PVT原理PVT的核心思想和结构PVT模块结构体素分支点分支 代码实现 论文题目&#xff1a;PVT: Point-Voxel Transformer for Point Cloud Learning发布期刊&#xff1a;International Journal of Intelligent Systems通讯地址&#xff1a;杭州电子科技大学&伦敦大学…

善于善行——贵金属回收

在当今社会&#xff0c;贵金属回收已成为一项日益重要的产业。随 着科技的不断进步和人们对资源可持续利用的认识逐渐提高&#xff0c;贵金属回收的现状也备受关注。 目前&#xff0c;贵金属回收市场呈现出蓬勃发展的态势。一方面&#xff0c;贵金属如金、银、铂、钯等在众多领…

【C语言】结构体超详细全讲解 (代码+万字文字+画图讲解)

目录 1.什么是结构体类型 2.结构体变量的创建 3.结构体变量的初始化 4.结构体的特殊声明 5.typedef重定义结构体变量&#xff08;两种方式&#xff09; 6.结构体自引用 7.创建结构体指针变量 8.结构体内容的访问 8.1直接访问&#xff1a; 8.2 结构体指针访问 9.结构体内…

IPD推行成功的核心要素(二十二)IPD流程持续优化性地推出具备商业成功潜力的产品与解决方案

产品开发是非常复杂的。随着创新环境的快速发展&#xff0c;大部分研发型企业普遍会面临着这些核心问题&#xff1a;如何快速响应市场的变化&#xff1f;如何推出更有竞争力的产品&#xff1f;如何在竞争中脱颖而出&#xff1f;因此&#xff0c;往往随着企业的规模化发展&#…

深度优先搜索(DFS)在图的运行过程

深度优先搜索(DFS)在图的运行过程 深度优先搜索算法(DFS)C语言实现运行DFS并记录结果节点发现时间和完成时间:图a是一个有向图,为了清晰起见,我们首先假设图a的具体结构如下(节点和边的集合): 图a: 节点集合: {A, B, C, D, E, F} 边集合: {(A, B), (A, C), (B, D),…

带你了解Android Jetpack库中的依赖注入框架:Hilt

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 Hilt概述 Hilt是Google推出的一种用于Android的依赖注入&#xff08;Dependency Injection&#xff0c;DI&#xff09;框架&#xff0c;构建于…

Java 学习中使用文件、网络连接等资源时,未正确关闭资源,导致资源泄漏应该怎么办?

在Java编程中&#xff0c;处理文件、网络连接、数据库连接等资源时&#xff0c;如果没有正确关闭资源&#xff0c;就会发生资源泄漏。资源泄漏会导致系统性能下降、内存占用增加&#xff0c;甚至可能导致程序崩溃&#xff0c;特别是在高负载的系统中。 一、什么是资源泄漏&…

【C+继承】

继承 1.继承的概念及定义2.基类和派生类对象赋值转换3.继承中的作用域4.派生类的默认成员函数5.继承与友元6.继承与静态成员7.复杂的菱形继承及菱形虚拟继承8.继承的总结和反思 1.继承的概念及定义 ->继承的概念 继承的本质&#xff1a;就是继承的父类的成员 ->继承的…

《哈利波特:魔法觉醒》仅16个月欧美停服,引来“阴谋论”

易采游戏网9月11日消息&#xff1a;2022年&#xff0c;当网易宣布将与华纳兄弟合作推出《哈利波特&#xff1a;魔法觉醒》时&#xff0c;全球玩家一片欢腾。不仅在中国市场掀起了一股狂潮&#xff0c;也迅速进入了欧美市场&#xff0c;吸引了无数哈迷和卡牌游戏爱好者。令人始料…

vue+el-table 可输入表格使用上下键进行input框切换

使用上下键进行完工数量这一列的切换 <el-table :data"form.detailList" selection-change"handleChildSelection" ref"bChangeOrderChild" max-height"500"><!-- <el-table-column type"selection" width&quo…

视频融合共享平台LntonAIServer视频分析平台噪声监测优势

LntonAIServer的视频质量诊断功能中的噪声检测是一项关键技术&#xff0c;旨在帮助用户及时发现并解决视频流中的噪声问题&#xff0c;确保视频监控系统的稳定性和可靠性。 在视频监控系统中&#xff0c;噪声问题常常影响到视频画面的清晰度和可用性。噪声可能由多种因素引起&a…

基于SpringBoot+Vue的考研学习分享互助平台

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的考研学习…

仕考网:省考面试流程介绍,提前了解

省考面试流程介绍&#xff0c;一文带大家了解! 一、面试登记及抽签 考生通常需要提前10至30分钟到达指定地点进行登记。 考试工作人员核对考生身份证和面试通知书等相关证件后&#xff0c;进行抽签确定分组和进场顺序。 二、候考阶段 考生完成抽签后进入候考区等待考试。在…

空气开关跳闸的原因及解决办法

空气开关&#xff08;也称为断路器或空气断路器&#xff09;跳闸通常是因为电路中的某些问题导致的。下面是一些常见的原因及解决办法&#xff1a; 1. 过载 原因&#xff1a;当电路中的电流超过空气开关的额定值时&#xff0c;会导致过载保护动作&#xff0c;使空气开关跳闸。…

银行安全用电典型产品解决方案介绍-安科瑞-叶西平

应用背景 银行作为国家重要部门&#xff0c;是国家经济建设的中枢&#xff0c;也是消防的重点单位。用电安全是银行安全保卫工作 的一个重要环节。银行安保设施、数据中心、自助设施、办公设备等能耗单元对用电的连续性、稳定性和安 全性要求非常高&#xff0c;实时监测线路及…