来自 C# 应用程序的 MySqlBulkLoader 的问题
本文关键字:MySqlBulkLoader 问题 应用程序 来自 | 更新日期: 2023-09-27 18:30:50
我正在编写一个应用程序,每晚将一些数据从MSSQL导出到MySQL服务器。我使用一个简单的查询来获取前一天的所有数据,然后尝试了几种不同的方法来将其获取到 MySQL。最快的方法是使用MySqlBulkLoader,但由于某种原因,它不会移动所有数据。插入后,我将生成的文本文件中的记录与MySQL中的记录数进行比较,并且计数在某些情况下从1一直到10。
如果我采用相同的方法将数据获取到文本文件,但循环遍历文本文件的每一行,而不是批量上传并执行插入语句,则所有记录都会被导入。
这是我目前正在使用的批量上传代码。我最近添加了 FieldQuoteCharacter 以查看这是否有帮助,但它没有(当我添加它时,我使文本生成脚本将字段括在引号中)。
uploader.TableName = "testtable";
uploader.FieldTerminator = "'t";
uploader.LineTerminator = "'r'n";
uploader.NumberOfLinesToSkip = 0;
uploader.FileName = updateFile; //this is a variable pointing to the current file
uploader.Timeout = 120;
uploader.FieldQuotationCharacter = '"';
int totalExported = uploader.Load();
有什么想法吗?
看起来有点奇怪,但一时兴起,我决定在顶部用一个空行编写我的输出文件,然后设置 NumberOfLinesToSkip = 1。这样做之后,一切正常,没有记录丢失。有点奇怪。似乎将其设置为 0 不起作用,可能不受支持。
我遇到了类似的问题,它加载了文件中大约 2/3 的行,问题原来是 MySqlBulkLoader 生成的加载数据 sql 中本地关键字的行为。
默认情况下,MySqlBulkLoader.Local == true 似乎允许它使用本地文件,但也会影响无效行的错误处理。 当一行无效时,它不会抛出错误,而是会给你"警告"。 您可以通过对加载数据运行实际的 sql 命令来验证这一点并查看警告(这是 MySqlBulkLoader 使用的命令):
load data local infile '/Temp/bb7dd81c-c79f-49c7-9ae4-fdc8e48df6d5.csv'
ignore into table my_staging_tbl
fields terminated by ',' enclosed by '"' escaped by ''''
lines terminated by ''n'
这将输出受影响行的计数和所有警告的列表
就我而言,我将 LineTerminator 设置为"'"而不是"''r'",并且在禁止警告后,它仍然最终导入了大部分行。
您可以通过将 MySqlBulkLoader.ConflictOption 设置为 MySqlBulkLoaderConflictOption.Replace 而不是默认的 Ignore 来覆盖此行为。 请注意,这也会影响它处理重复键的方式。
有关 mysql 加载数据的更多信息:http://dev.mysql.com/doc/refman/5.7/en/load-data.html
如果您偶然发现这篇文章,正在寻找捕获这些警告的解决方案,那么就在这里。实际上,您需要在基础连接上添加一个事件处理程序来获取它们。喜欢这个:
connection.InfoMessage += new MySqlInfoMessageEventHandler(OnInfoMessage);
connection.Open();
MySqlBulkLoader bulkLoader = new MySqlBulkLoader(connection);
void OnInfoMessage(object sender, MySqlInfoMessageEventArgs e) {
MySqlCommand myCommand = new MySqlCommand("SHOW WARNINGS", (MySqlConnection)sender);
MySqlDataReader reader = myCommand.ExecuteReader();
while (reader.Read()) {
Console.WriteLine(reader[0].ToString() + " " + reader[1].ToString() + " " + reader[2].ToString());
}
}