【问题标题】:Stored procedure that accepts a query as parameter接受查询作为参数的存储过程
【发布时间】:2019-01-16 22:25:19
【问题描述】:

我正在尝试编写一个接受SELECT 查询并针对数据库列表执行它的 MySQL 存储过程。这甚至可以通过 MySQL 实现吗?

我们应用程序中的每个客户在同一个实例上都有自己的数据库。所有客户数据库的模式结构都是相同的。有时,我需要跨所有客户数据库(例如SELECT COUNT(*) FROM users)执行一个简单的 SELECT 查询。

我已经为常见的重复“实例范围”查询(如用户计数)创建了更多的存储过程,但我不想为一次性查询创建更多的存储过程(例如,查询由于错误代码导致的损坏记录、查询对于我们计划弃用的列等)。

我当前的解决方案是我有一个 node 脚本,我在本地运行该脚本以为每个数据库生成 SELECT 查询,然后使用 UNION 将它们全部连接起来以生成一个巨大的查询,然后我在数据库实例上执行该查询。

SELECT 'customerdb1' AS customer,
       COUNT(*) AS user_count
FROM customerdb1.users
UNION
SELECT 'customerdb2' AS customer,
       COUNT(*) AS user_count
FROM customerdb2.users
UNION
SELECT 'customerdb3' AS customer,
       COUNT(*) AS user_count
FROM customerdb3.users

【问题讨论】:

  • 当然可以,但听起来是个坏主意。存储过程可以在可能的不同 MySQL 用户和/或权限上运行。。您将如何控制它的安全性? .
  • 存储过程将仅由对所有其他数据库只有SELECT 权限的特殊帐户使用。出于什么原因这是一个坏主意?安全?表现?可维护性?
  • @dashmug 这是一个关于任意 SQL 输入的笑话:xkcd.com/327 创建存储过程以抽象出数据库逻辑(查询)。允许任意 SQL 代码通过会破坏最初的目的。相反,您可以完全阐明和定义客户需要的所有可能功能 - 创建单独的存储过程 - 然后提供有关可用过程的文档。这种严谨性将自我记录可用功能(使用单独的存储过程),并向您的客户和您自己充分阐明应用程序的行为。
  • 是的,我知道小鲍比桌。实际上,在我想运行我的临时查询(不是我的用户)的意义上,它是“任意的”。我试图避免检索数据库列表然后对每个数据库执行查询的样板。
  • 您的第一句话说“存储过程接受任意 SELECT 语句”,就这个词而言,它实际上是任何东西。您的后续问题“这是一个安全问题吗?”强调它仍然是任意的和未知的。将“任意”改为“我预先定义的陈述”,你会得到截然不同的答案。

标签: mysql amazon-aurora


【解决方案1】:

您可以使用PREPARE and EXECUTE 在存储过程中执行此操作,但以这种方式运行任意 SQL 被认为是一个安全漏洞。您说该程序只能由特殊帐户使用,但仅允许该程序存在是有风险的。如果权限被修改并允许任何人运行该过程怎么办?

跨多个模式运行此查询也会很慢,因为 MySQL 每个查询只运行一个线程。它必须连续运行查询,将结果收集到一个临时表中。

您还对任何单个 SQL 查询的长度有限制,即 max_allowed_packet。这应该很大,但如果你有足够的 UNION 项,你仍然可以超过长度。

我在一个像您描述的那样的网站上工作,其中有许多模式,每个客户一个,具有相同的表。当我们想要跨所有模式运行查询时,我会在许多并行线程中运行一个简单的查询(没有UNION),并在应用程序代码中收集结果。


有关允许输入任意 SQL 的存储过程的有趣故事,请参阅 https://thedailywtf.com/articles/For-the-Ease-of-Maintenance

【讨论】:

  • 对——限制工作线程的数量是个好主意。不要盲目地运行与模式数量一样多的线程。这是设计一个在今天运行良好但在未来某个时间在您的客户数量增加后会突然中断的好方法。
  • 意外删除了我的其他评论,将其归咎于在我的手机上浏览 stackoverflow 并按错了您应该做的事情。但是,即使您没有运行与模式一样多的线程。您仍然必须将所有表数据或需要的数据存储在内存中,以便在应用程序中使用,如果客户计数或数据将来仍然可能中断成长
  • 在示例中,它只是一个SELECT COUNT(*),它将为每个模式返回一个整数。在这之前您需要大量的模式,这会导致您的应用程序出现可伸缩性问题。如果您达到了这一点,那么您可以将每个结果存储在一个表中。
  • 是的,我说过,这也是在我的其他第一个意外评论中。因为这是一个简单的 Count 查询示例,所以应该没问题。 topicstarter 正在讨论任意 SELECT 查询,可能需要的数据或排序要求可能会占用更多资源,并且确实可能​​需要表存储来“清除”您建议的 ram 内存
  • 这让我更加确信执行任意 SQL 的一刀切的过程不是一个好主意。需要部分根据查询的性质来选择如何处理结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-20
  • 2019-01-11
  • 1970-01-01
  • 2021-09-11
  • 2014-05-10
  • 2020-08-02
  • 2013-10-10
相关资源
最近更新 更多