【问题标题】:Error while using BulkCopy (Failed to read the result set)使用 BulkCopy 时出错(无法读取结果集)
【发布时间】:2020-12-17 13:53:54
【问题描述】:

我开发了一个 vb.net 应用程序,它使用来自另一台服务器的 API 请求填充表,并使用 MySqlBulkCopy 将这些表传输到 MySql 数据库。

这是我用来批量复制多个表的辅助类(仅初始化一次)。执行 writeToServer() 会引发以下错误:“读取结果集失败。”没有任何进一步的信息。

    Private connStr As String
    Private conn As MySqlConnection
    Private blkInsert As MySqlBulkCopy
    Public ErrorMessage As String
    Public ErrorTableName As String

    Public Sub New()
        connStr = My.MySettings.Default.MyBaseConnectionString
        conn = New MySqlConnection(connStr)

        blkInsert = New MySqlBulkCopy(conn)
    End Sub

    Public Function WriteToMySql(destinationTableName As String, localTable As DataTable) As Boolean
        blkInsert.DestinationTableName = destinationTableName

        Try
            blkInsert.WriteToServer(localTable)
        Catch ex As Exception
            ErrorMessage = ex.Message
            ErrorTableName = destinationTableName
            Return False
        End Try

        Return True
    End Function
End Class

我将要复制到的表的名称以及包含数据的表传递给 WriteToMySql。

If Not (blkInsert.WriteToMySql("tb_vendor", Ds.Vendor) AndAlso
                blkInsert.WriteToMySql("tb_group", Ds.Group) AndAlso
                blkInsert.WriteToMySql("tb_subgroup", Ds.SubGroup) AndAlso
                blkInsert.WriteToMySql("tb_product", Ds.Product) AndAlso
                blkInsert.WriteToMySql("tb_product_attribute", Ds.Characteristic) AndAlso
                blkInsert.WriteToMySql("tb_product_attributes", productAttributes) AndAlso
                blkInsert.WriteToMySql("tb_encoded_names", productNamesEncoded) AndAlso
                blkInsert.WriteToMySql("tb_pictures", Ds.PictureNew) AndAlso
                blkInsert.WriteToMySql("tb_group_category", groupCategories)) Then
...

错误出现不一致,当它出现时,重新执行(使用相同的表)没有帮助,它会触发相同的错误,就像它与表本身有关。我正在插入 6 个表,其中包含最多行的表会触发该错误(始终是同一个表),而其他任何表都被成功复制。

修复错误的唯一方法是从 API 加载数据(重新初始化并重新填充表格)并尝试插入。大多数情况下,它不会导致该错误,它会触发超级随机。

任何帮助将不胜感激,如果需要,我可以提供更多信息。 提前致谢。

编辑(回答问题):造成问题的数据表包含不超过 200k 行,但我已经尝试插入更大的表(2-3m 行)来检查如果它必须与大小有关,则不存在错误。

当错误发生时,我看到 BulkCopy 插入了一部分行,然后抛出了错误。数据库上基本上有插入的行,但不是全部。

Ds 是我从 API 填写的变量(数据集)的名称。其他独立表由我随后生成,用于处理数据和生成所需值。

我没有设置任何超时,但是在调试时我看到它等于0,这意味着无论需要多长时间它都应该等待。

我试图在调试时触发错误,它最近出现在发布版本上。当我这样做时,我会提供更多信息。

Edit2(堆栈跟踪和内部异常)

Failed to read the result set.

堆栈跟踪:

   at MySqlConnector.MySqlDataReader.ActivateResultSet()
   at MySqlConnector.MySqlDataReader.<CreateAsync>d__97.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at MySqlConnector.Core.CommandExecutor.<ExecuteReaderAsync>d__0.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at MySqlConnector.MySqlCommand.<ExecuteNonQueryAsync>d__69.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at MySqlConnector.MySqlBulkLoader.<LoadAsync>d__73.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1.ConfiguredValueTaskAwaiter.GetResult()
   at MySqlConnector.MySqlBulkCopy.<WriteToServerAsync>d__29.MoveNext()

--- End of stack trace from previous location where exception was thrown ---

   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
   at MySqlConnector.MySqlBulkCopy.WriteToServer(DataTable dataTable)
   at PolyBridge.BulkInsert.WriteToMySql(String destinationTableName, DataTable localTable)

InnerException:

Error during LOAD DATA LOCAL INFILE

【问题讨论】:

  • 欢迎来到 Stack Overflow。大桌子有多大?操作是否超时?也就是说,它会运行一定时间然后失败吗?你如何创建那些Ds.Tablename 对象?您能否从ex.StackTraceex.InnerException 中收集有关失败原因的任何信息?如果您edit 提出将这些值放在这里的问题,我们可能会为您提供进一步的帮助。
  • 你检查过是否有内部异常?
  • 另外,如果您可以将堆栈跟踪输出添加到您的问题中,将会很有帮助。
  • 我已编辑帖子以回答您的问题。我现在正在积极尝试触发该错误。 5次,目前没有错误,我希望它很快再次触发。然后,我将提供更多信息。
  • 啊哈。 在 LOAD DATA LOCAL INFILE 期间失败。这有帮助。

标签: mysql .net vb.net sqlbulkcopy connector-net


【解决方案1】:

尝试将bulk copy timeout 设置为一个较大的数字,例如 3600 秒一小时。

    blkInsert = New MySqlBulkCopy(conn)
    blkInsert.BulkCopyTimeout = 3600

你也可以用这个完全禁用超时

    blkInsert.BulkCopyTimeout = 0

【讨论】:

  • 我添加了一个手表来在调试时检查该值,它似乎设置为 0,即使我没有这样做。我相信这是默认的。
  • 我不具体了解Connector/NET,但我知道这个API的SQL Server版本有一个默认设置,需要重写。我用那个 API 用了一小时。 (3600 秒)。我建议这样做是因为您面临的间歇性情况对我来说就像是超时。可能是别的东西。
【解决方案2】:

我非常了解 SqlServer 和 Oracle,但 MySql 不是我的专业领域。但是,在检查 Google 是否有类似情况时,我确实发现了一些可以解释它的东西:超过 max_allowed_pa​​cket 大小。

这只会发生在最大的文件上,显而易见的解决方案是将此设置提高到最大值:

set global max_allowed_packet=268435456

【讨论】:

  • 我已经考虑过了,但是我没有尝试修改它,因为我已经成功地插入了更大的表,但是尝试并没有什么坏处。我刚刚设置了它,如果它解决了问题会通知你。
  • @thearctoss 请注意,您服务器上的其他东西也可能正在设置/重置此值,这可能解释了为什么问题随机发生,因此您需要确保在运行之前始终正确设置SqlBulkCopy。
猜你喜欢
  • 2013-01-18
  • 1970-01-01
  • 1970-01-01
  • 2016-01-01
  • 2019-08-10
  • 2013-06-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多