在“太多”线程上运行(linux)BCP有任何特定问题吗?

时间:2018-10-08 23:42:04

标签: bcp

在多个线程上运行Microsoft的BCP实用程序(在CentOS 7,https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-migrate-bcp?view=sql-server-2017上)是否存在任何特定问题?谷歌搜索找不到很多,但是正在寻找一个似乎与此有关的问题。

使用某种形式的代码将一组大型TSV文件从HDFS复制到远程MSSQL Server

bcpexport() {
    filename=$1
    TO_SERVER_ODBCDSN=$2
    DB=$3 
    TABLE=$4 
    USER=$5
    PASSWORD=$6
    RECOMMEDED_IMPORT_MODE=$7 
    DELIMITER=$8 

    echo -e "\nRemoving header from TSV file $filename"
    echo -e "Current head:\n"
    echo $(head -n 1 $filename)
    echo "$(tail -n +2 $filename)" > $filename
    echo "First line of file is now..."    
    echo $(head -n 1 $filename)

    # temp. workaround safeguard for NFS latency
    #sleep 5 #FIXME: appears to sometimes cause script to hang, workaround implemented below, throws error if timeout reached 
    timeout 30 sleep 5

    echo -e "\nReplacing null literal values with empty chars"
    NULL_WITH_TAB="null\t" # WARN: assumes the first field is prime-key so never null
    TAB="\t"
    sed -i -e "s/$NULL_WITH_TAB/$TAB/g" $filename
    echo -e "Lines containing null (expect zero): $(grep -c "\tnull\t" $filename)"

    # temp. workaround safeguard for NFS latency
    #sleep 5 #FIXME: appears to sometimes cause script to hang, workaround implemented below 
    timeout 30 sleep 5

    /opt/mssql-tools/bin/bcp "$TABLE" in "$filename" \
        $TO_SERVER_ODBCDSN \
        -U $USER -P $PASSWORD \
        -d $DB \
        $RECOMMEDED_IMPORT_MODE \
        -t "\t" \
        -e ${filename}.bcperror.log
}

export -f bcpexport
parallel -q -j 7 bcpexport {} "$TO_SERVER_ODBCDSN" $DB $TABLE $USER $PASSWORD $RECOMMEDED_IMPORT_MODE $DELIMITER \
    ::: $DATAFILES/$TARGET_GLOB 

其中$DATAFILES/$TARGET_GLOB构造了一个glob,该glob列出了目录中的一组文件。

在为一组TSV文件运行此代码时,有时发现并行BCP线程中的某些(不是全部)失败,即。一些文件成功复制到MSSQL Server

  

开始复制...

     

5397376行已复制。

     

网络数据包大小(字节):4096

     

时钟时间(毫秒)总计:154902平均:(每秒34843.8行)

而其他人输出错误消息

  

开始复制...

     

BCP复制失败

通常情况下,请参见此模式:在返回的前几个线程中执行了一些成功的BCP复制操作,然后一堆失败的线程返回其输出,直到用完文件为止(GNU Parallel仅在整个线程完成显示后才返回输出就像顺序的一样。

请注意,代码中有-e选项,用于为每个BCP插入操作生成错误文件(请参见https://docs.microsoft.com/en-us/sql/tools/bcp-utility?view=sql-server-2017#e)。在观察到这些失败行为后检查文件时,所有文件均为空白,没有错误消息。

只有在线程数> = 10时才看到这种情况(并且仅对于某些数据集(假设文件总数与文件大小有关,但是...)),因此看不到错误在使用〜7个线程时远远不够,这进一步使我怀疑这与多线程有关。

(通过free -mh监视系统资源表明,通常〜13GB或RAM总是可用的。

可能要注意,bcp试图复制的数据可能有〜500000-1000000个记录,每个记录的上限为〜100列。

有人知道这里会发生什么吗?请注意,使用BCP以及GNU并行和多线程是一个相当新的东西。

2 个答案:

答案 0 :(得分:0)

否,没有特定于在多个线程中运行的BCP程序的问题。您似乎在跟踪我要说的问题是系统资源。您是否在增加线程数的同时监视了系统资源?如果有的话,当内存/ CPU /网络资源不足时,BCP可能会正常执行。关于“ -e”选项,它意味着输出数据错误。登录错误,错误的表名...使用-e选项创建的文件中未报告许多其他错误。当使用“ -e”选项获得输出时,您会看到诸如“值被截断”之类的信息,诸如此类...将为您提供有争议的行号和示例数据。

答案 1 :(得分:0)

TLDR :添加更多线程以同时运行以具有bcp个数据复制文件,似乎会影响使用写入指令的端点MSSQL Server,从而导致{{ 1}}线程失败(也许超时了?)。当线程数过多时,似乎取决于bcp复制的文件大小(即文件中的记录数以及每条记录的宽度(即。列数))。

长版(我的理论有更多原因)

1。 当运行大量bcp线程并查看在计算机(https://clustershell.readthedocs.io/en/latest/tools/clush.html)上启动的进程时

bcp

看到一堆睡眠过程(注意ps -aux | grep bcp ,请参阅https://askubuntu.com/a/360253/760862),如下所示(增加了换行符以提高可读性)

  我135296 14.5 0.0 77596 6940 S 00:32 0:01

     

/ opt / mssql-tools / bin / bcp TABLENAME在/path/to/tsv/1_16_0.tsv -D -S MyMSSQLServer -U myusername -P -d myDB -c -t \ t -e / path / to / logfile

这些线程似乎睡眠很长时间。进一步调试这些线程为何处于休眠状态表明它们可能实际上正在完成其预期的工作(这将进一步暗示问题可能来自BCP本身(参见https://stackoverflow.com/a/52748660/8236733)。来自https://unix.stackexchange.com/a/47259/260742https://unix.stackexchange.com/a/36200/260742

  

处于S状态的进程通常处于阻塞的系统调用中,例如读取或写入文件或网络,或等待另一个被调用程序完成。

(例如,写入ODBCDSN中指定给S的MSSQL Server端点目标)

  

当您的进程正在执行可能阻止的读取操作时,它将处于S状态。在等待信号量或其他同步原语时也可能会发生...这都是正常现象,是正常现象,通常不是问题...您不希望它在等待用户输入时浪费CPU。

2。。当运行不同组的文件时,每个文件的记录量(例如500000-1000000行/文件的范围)和每个文件的记录宽度(〜10) -100列/行),发现在宽度或数量非常大的情况下,运行一组固定的bcp线程会失败。

例如。对于一组约33个TSV,每组约500000行,每行约100列宽,一组30个线程将写入前几个OK,但随后所有其余线程将开始返回失败消息。结合@jamie的回答,返回的失败消息是bcp错误这一事实并不一定意味着它与所讨论的数据内容有关。错误日志文件上没有实际内容,他们的帖子这样说

  

关于“ -e”选项,它旨在输出数据错误。登录错误,错误的表名...使用-e选项创建的文件中未报告许多其他错误。当您使用“ -e”选项获得输出时,您会看到诸如“值被截断”之类的信息,诸如此类...将为您提供有争议的行号和示例数据。

同时,一组约33个TSV,每组约500000行,每行约100宽,仍然使用30个"BCP copy in failed"线程,将快速完成而不会出错(减少线程数时也会更快)线程或文件集)。这里唯一的区别是bcp复制到MSSQL Server的数据的整体大小。

所有

bcp

仍然显示在每种情况下,运行线程的计算机仍具有〜15GB的可用RAM(这又是为什么我怀疑问题与远程MSSQL Server端点有关,而不是与代码或本地计算机本身有关的原因) )。

3。。运行(2)中的某些测试时,发现手动终止free -mh 进程(通过parallel),然后尝试远程截断测试在本地计算机上用CTL+C写入表将花费很长时间(与手动登录MSSQL Server并在数据库中执行/opt/mssql-tools/bin/sqlcmd -Q "truncate table mytable"相对)。再次,这使我认为这与MSSQL Server的连接过多有关,只是不知所措。