从 Azure Blob 存储批量插入时出现 ERRORFILE 问题

Posted

技术标签:

【中文标题】从 Azure Blob 存储批量插入时出现 ERRORFILE 问题【英文标题】:Issue with ERRORFILE when BULK INSERTing from Azure Blob Storage 【发布时间】:2021-03-06 23:19:51 【问题描述】:

我正在尝试将大量 CSV 文件从 Azure Blob 存储批量插入到我的 Azure SQL 数据库中。

这是我试图实现这一目标的方法:

IF EXISTS(SELECT * FROM SYSOBJECTS WHERE ID = OBJECT_ID('[sqldb1].[dbo].[TABLE_A_RAW]'))
    DROP TABLE [sqldb1].[dbo].[TABLE_A_RAW];
    
CREATE TABLE [sqldb1].[dbo].[TABLE_A_RAW]
(
        [COL1] varchar(60),
        [COL2] varchar(60),
        [COL3] varchar(60),
        [COL4] varchar(60),
        [COL5] varchar(60)
);
        
BULK INSERT [sqldb1].[dbo].[TABLE_A_RAW]
FROM 'TABLE_A.CSV'
WITH
    (
        DATA_SOURCE = 'myazureblobstoragecontainer',
        FORMAT = 'CSV',
        ERRORFILE = 'load_errors_TABLE_A',
        ERRORFILE_DATA_SOURCE = 'myazureblobstoragecontainer',
        FIRSTROW = 2,
        FIELDTERMINATOR = '0xE29691',
        ROWTERMINATOR = '0x0a'
    )
GO
    
IF EXISTS(SELECT * FROM SYSOBJECTS WHERE ID = OBJECT_ID('[sqldb1].[dbo].[TABLE_B_RAW]'))
    DROP TABLE [sqldb1].[dbo].[TABLE_B_RAW];
    
CREATE TABLE [sqldb1].[dbo].[TABLE_B_RAW]
(
        [COL1] varchar(60),
        [COL2] varchar(60),
        [COL3] varchar(60),
        [COL4] varchar(60),
        [COL5] varchar(60),
        [COL6] varchar(60),
        [COL7] varchar(60),
        [COL8] varchar(60),
        [COL9] varchar(60)
);
        
BULK INSERT [sqldb1].[dbo].[TABLE_B_RAW]
FROM 'TABLE_B.CSV'
WITH
    (
        DATA_SOURCE = 'myazureblobstoragecontainer',
        FORMAT = 'CSV',
        ERRORFILE = 'load_errors_TABLE_B',
        ERRORFILE_DATA_SOURCE = 'myazureblobstoragecontainer',
        FIRSTROW = 2,
        FIELDTERMINATOR = '0xE29691',
        ROWTERMINATOR = '0x0a'
    )
GO
   

上面的代码是在我从事一个几乎相同的项目(具有相同的部署)时开发的,它运行时没有任何问题。当我尝试为我当前的项目运行上面的代码时,错误日志文件被创建,表也是如此(如预期的那样),但它们都是空的,我得到了这些错误:

消息 4861,第 16 级,状态 1,第 17 行 无法批量加载,因为无法打开文件“load_errors_TABLE_A”。操作系统错误代码80(文件存在。)。

消息 4861,第 16 级,状态 1,第 17 行 无法批量加载,因为无法打开文件“load_errors_TABLE_A.Error.Txt”。操作系统错误代码80(文件存在。)。

消息 4861,第 16 级,状态 1,第 50 行 无法批量加载,因为无法打开文件“load_errors_TABLE_B”。操作系统错误代码80(文件存在。)。

消息 4861,第 16 级,状态 1,第 50 行 无法批量加载,因为无法打开文件“load_errors_TABLE_B.Error.Txt”。操作系统错误代码80(文件存在。)。

错误文件仅在我运行上面的代码时创建,这意味着它们在运行上面的代码之前不存在,因为错误消息似乎表明。当我注释掉 ERRORFILEERRORFILE_DATA_SOURCE(即ERRORFILE = 'load_errors_TABLE_A',ERRORFILE = 'load_errors_TABLE_B',ERRORFILE_DATA_SOURCE = 'myazureblobstoragecontainer',)的行并再次运行脚本时,批量插入完成且没有任何错误(但错误文件显然,不要最终被创建)。

我想BULK INSERT WITH ERRORFILEs 这样我就可以跟踪操作期间发生的任何截断,就像我在之前的项目中所做的那样。我尝试寻找类似的帖子,但它们似乎都与本地 BULK INSERT 操作有关,其中错误日志文件也在本地创建/存储。正如我上面提到的,前一个项目和这个项目的部署几乎相同 - 它们都运行 SQL Server 2014 (12.0.2000.8),我对 Azure DB 和 Blob 存储帐户 + 容器都有读/写访问权限。

【问题讨论】:

你的 csv 文件有标题吗?这个question对你有帮助吗? 是的,确实如此,但我非常怀疑问题出在 CSV 文件中,因为当我注释掉创建错误日志文件的代码时,它们会被批量插入。 【参考方案1】:

    您的 SAS 密钥尚未过期,对吧?请检查允许的权限

    您在创建 SECRET 时是否删除了问号

CREATE DATABASE SCOPED CREDENTIAL UploadInvoices
WITH IDENTITY = 'SHARED ACCESS SIGNATURE',
SECRET = 'sv=2019-12-12******2FspTCY%3D'

我尝试了以下测试,效果很好。我的 csv 文件没有标题。

CREATE MASTER KEY ENCRYPTION BY PASSWORD = '***';
go

CREATE DATABASE SCOPED CREDENTIAL UploadInvoices
WITH IDENTITY = 'SHARED ACCESS SIGNATURE',
SECRET = 'sv=2019-12-12&ss=bfqt&srt=sco&sp******%2FspTCY%3D'; -- dl


CREATE EXTERNAL DATA SOURCE MyAzureInvoices
    WITH (
        TYPE = BLOB_STORAGE,
        LOCATION = 'https://***.blob.core.windows.net/<container_name>',
        CREDENTIAL = UploadInvoices
    );

BULK INSERT production.customer
FROM 'bs140513_032310-demo.csv'
WITH
    (
        DATA_SOURCE = 'MyAzureInvoices',
        FORMAT = 'CSV',
        ERRORFILE = 'load_errors_TABLE_B',
        ERRORFILE_DATA_SOURCE = 'MyAzureInvoices',
        FIRSTROW = 2
    )
GO

【讨论】:

【参考方案2】:

罪魁祸首最终是权限,正如@joseph-xu 在下面的回答中所建议的那样。

当前项目:

旧项目:

我用于此项目的 Blob 存储的 SAS 密钥缺少 DELETEDELETE VERSION 权限,如果您想在 BULK INSERT 语句中包含 ERRORFILEERRORFILE_DATA_SOURCE,这是必需的。据我所知,微软的文档中没有提到这一点(错误消息也没有暗示这是问题所在)。

我只是创建了一个具有 ALL 权限的新 SAS 密钥,用它来创建一个新的 DATABASE SCOPED CREDNETIALEXTERNAL DATA SOURCE,然后再次运行我的代码并且它工作了。

【讨论】:

以上是关于从 Azure Blob 存储批量插入时出现 ERRORFILE 问题的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法从本地 Azure Blob 存储批量插入?

从 Azure Blob 存储文件名下载文件时出现的问题包含哈希 (#)

Azure SQL - 从 Azure 文件而不是 Blob 批量插入

在从 blob 存储中获取文件并传递给模型进行预测时出现 azure aci webservice 的超时错误

Azure Databricks 在 Blob 存储上打开文件时出现问题

在 Azure Blob 存储中上传文件时出现 InvalidAuthenticationInfo 错误