【问题标题】:Sql Server CLR file system access from UDF从 UDF 访问 Sql Server CLR 文件系统
【发布时间】:2011-07-27 13:31:11
【问题描述】:

我编写了一个简单的 UDF,它应该绘制一个图形并将其保存在磁盘上。 实际上,我使用 UDF 作为 SQL SERVER 和 R 之间的代理,因此 UDF 仅通过 DCOM 从 SQL SERVER 将 R 脚本传递给 R 引擎。在我尝试绘制图形或将其保存到磁盘之前,一切正常。我创建了具有 UNSAFE 权限的程序集。

所以,它是这样的: SQL 引擎 -> UDF -> (D)COM SERVER -> R -> (D)COM SERVER -> UDF -> SQL 引擎。

那么,我的第一个问题是,我可以从 UDF 创建 GUI 吗?我猜不是,但值得一问。

第二个问题是,为什么具有 UNSAFE 权限的程序集无法访问文件系统。我没有收到任何错误,只是没有任何反应。

R 环境位于不同的地址空间中,因此我看不出任何原因导致 SQL 引擎的 CLR 权限会影响它。

谢谢

编辑:

我尝试对程序做同样的事情。现在创建了一个空文件。这是我的 R 测试代码:

jpeg("C:\\test1.jpg"); x <- rnorm(100); hist(x); dev.off()

知道这里发生了什么吗?

【问题讨论】:

  • 我会运行 SysInternals Filemon 或 Process Monitor 并尝试确定程序集试图在文件系统中执行的操作。您可以使用其中一种工具获得一些可见性。

标签: sql-server r clr user-defined-functions sqlclr


【解决方案1】:
  1. 您不能从服务器端代码实例化 GUI
  2. UNSAFE 很危险,EXTERNAL_ACCESS 会更好,因为它仍然允许文件系统访问
  3. 如果没有错误,则很有可能您的代码运行正确,但它正在做的事情与您期望的不同;可以添加一些调试代码或附加调试器吗?
  4. 这里的过程比 UDF 更合适,因为they are much more flexible

但目前尚不清楚您为什么要这样做。在 SQL Server 之外编写一个小(?)程序以从数据库中获取数据、调用 R 程序并保存图像可能会容易得多。 SQL Server 中的服务器端代码非常适合处理数据,但通常对于与文件系统和外部资源交互非常尴尬,即使您使用 CLR 代码也是如此。

是否有任何特定原因需要从 SQL Server 中执行此操作?

【讨论】:

  • 原因是我正在为一个更大的项目制作一个小演示。想法是从 ssms 窗口做所有事情。我知道这是一种奇怪的方法,但我别无选择。另外,我需要 UNSAFE 权限,因为加载了一些非托管 dll。同样,这只是一个演示,所以我不担心安全性。我使用了带有 dll 的 Visual Studio 的即时调试器,一切正常,所以我认为问题不在于 dll 代码。明天我会在程序上试试运气,但这可能是一个很长的机会。非常感谢您的回答。
  • @Klark 为什么对如何运行演示“别无选择”?您的程序的输出似乎是包含图形的文件,因此 SSMS 完全是错误的工具。为什么不为您的演示编写一个外部程序并从批处理文件启动它(如果您没有时间构建 GUI)?很抱歉没有提供帮助,但您无缘无故地以一种非常奇怪的方式做事。
【解决方案2】:

要访问文件系统,最好使用 SSIS。您可以随时编辑和测试包,在需要时进行日志记录。您还可以轻松地将 VisualStudio 中的 GUI 添加到此包中。由于可能存在安全问题,从 DatabaseEngine 访问文件系统不是最佳实践。

【讨论】:

    【解决方案3】:

    我的第一个问题是,我可以从 UDF 创建 GUI 吗?

    您可以使用System.Drawing 创建和/或操作图像,但是:

    • 仅当程序集具有 PERMISSION_SETUNSAFE,并且
    • 您将System.Drawing 程序集加载到SQL Server 中,如UNSAFE

    第二个问题是,为什么具有 UNSAFE 权限的程序集无法访问文件系统。我没有收到任何错误,只是没有任何反应。

    标记为EXTERNAL_ACCESSUNSAFE 的程序集允许访问外部资源。尝试这样做并且没有收到错误表明它是允许的。虽然,目前尚不清楚“什么都没有发生”是什么意思,因为要么你有一个 catch 块正在“吞下”错误,要么文件是在你不期望的目录中创建的,因为你使用了相对路径而不是绝对路径。

    外部资源访问的两个问题(尽管它们是捆绑在一起的)是:

    • 哪个 Windows / Active Directory 登录正在用于该访问。默认情况下,SQLCLR(就像xp_cmdshell)将在MSSQLSERVER 进程的“登录身份”帐户的安全上下文下访问系统。或者,您可以启用模拟,这将假定执行 SQLCLR 代码的任何人的安全上下文,假设登录(在 SQL Server 中)与 Windows / Active Directory 帐户相关联。 SQL Server 登录不能使用模拟。

    • 根据访问外部资源的帐户,他们对该资源的权限是什么?如果是文件系统,该帐户是否具有对指定路径的写入权限?

    根据给出的 R 示例(即创建 C:\test1.jpg),并假设未使用模拟:MSSQLSERVER(或 MSSQL${InstanceName} ) 服务以对 C:\ 的写入权限运行?请记住,这是运行 SQL Server 的服务器的 C: 驱动器,而不是您的本地计算机,除非此 SQL Server 实例正在您的计算机上运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-18
      • 2012-10-16
      • 2017-02-04
      • 1970-01-01
      • 1970-01-01
      • 2020-08-12
      • 2019-08-19
      相关资源
      最近更新 更多