SQL Server 随机超时问题

Posted

技术标签:

【中文标题】SQL Server 随机超时问题【英文标题】:SQL Server random timeout issue 【发布时间】:2017-04-24 04:18:14 【问题描述】:

你好,所以

我目前正在尝试运行处理 apx ~50k 记录的存储过程。它将记录排序到不同的表中,删除一些记录等。

但是,相对较长的预处理语句总是会导致以下错误:

> [2016-12-08 19:28:24] local.INFO: PDOException: SQLSTATE[HY000]:
> General error: 20003 Adaptive Server connection timed out [20003]
> (severity 6) [(null)] in
> /vendor/laravel/framework/src/Illuminate/Database/Connection.php:479
> Stack trace:
> #0 /vendor/laravel/framework/src/Illuminate/Database/Connection.php(479):
> PDOStatement->execute()
> #1 /vendor/laravel/framework/src/Illuminate/Database/Connection.php(762):
> Illuminate\Database\Connection->Illuminate\Database\closure(Object(Illuminate\Database\SqlServerConnection),
> 'EXEC dbo.cleanD...', Array)
> #2 /vendor/laravel/framework/src/Illuminate/Database/Connection.php(725):
> Illuminate\Database\Connection->runQueryCallback('EXEC dbo.cleanD...',
> Array, Object(Closure))
> #3 /vendor/laravel/framework/src/Illuminate/Database/Connection.php(480):
> Illuminate\Database\Connection->run('EXEC dbo.cleanD...', Array,
> Object(Closure))
> #4 /vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php(317):
> Illuminate\Database\Connection->statement('EXEC dbo.cleanD...')
> #5 /vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php(237):
> Illuminate\Database\DatabaseManager->__call('statement', Array)

让我明白的是,通过使用 laravel 块,我能够毫无意外地插入大约 5 万条记录:

$data = $data->chunk(500);

foreach ($data as $rows) 
    Log::info("INSERT START: " . date('l jS \of F Y h:i:s A'));
    DB::table("the.db")->insert($rows->toArray());

但只要存储过程运行(可能需要大约 2-4 分钟)

我收到上述错误。我尝试了很多不同的解决方案,包括将存储过程分解为更小的存储过程,但仍然出现错误。

总是同样的错误:

General error: 20003 Adaptive Server connection timed out [20003] (severity 6) [(null)] in /vendor/laravel/framework/src/Illuminate/Database/Connection.php:479

我偷偷怀疑某处(在 laravel?php.ini?)我可能不得不为 数据库

设置超时限制

任何帮助,提前谢谢!

【问题讨论】:

是否有可能将查询分解为几个较小的查询?另外,您可以使用 SQL Server 作业吗? 我做到了,不幸的是,花费最多时间的脚本需要保持在一起 如果可能的话,可能值得考虑将其设为 Job,特别是如果它按固定时间表运行。 这是一个每月上传一次的巨大 excel 表并被处理,我可能会重做逻辑(我刚从这里开始)我之前的人做了所有的“业务逻辑”数据库 是的,一旦有时间,我绝对会建议您-数据库通常对于数据处理类型的任务非常快,对于业务逻辑非常慢(而且显然,将它们分开是更好的架构,您不这样做)不希望在数据库层中出现业务逻辑,原因与它不应该出现在 UI 中的原因相同)。 【参考方案1】:

除了@user3158900 提供的解决方案之外,我知道我在 cmets 中提到了这一点,但只是在这里重申一下(因为 cmets 可能会被删除),如果查询可以,您可能需要考虑使用SQL Server Job不能再分解了。除了运行 SQL 脚本之外,作业还可以做各种事情(集成包、命令行应用程序、脚本等),因此它们非常适合自动执行日常管理类型的任务。

如果您要离开 SQL Server,Oracle 也有 job scheduler,但我不太熟悉。

既然您表示您计划在某个时候将逻辑移出 SQL Server,一旦您有时间,就有一种可能(如果您碰巧使用的是 Windows 服务器,我强烈建议您这样做,因为我拥有 Microsoft 股票: )) 是编写一个控制台应用程序并使用Windows Task Scheduler 按照您选择的时间表运行它。您甚至可以在不打开控制台窗口的情况下让它在后台运行。

【讨论】:

谢谢 - 如果 mssql 有一个用于存储过程的“即发即弃”选项(无需使用触发器等设置单独的表),那将会非常有帮助【参考方案2】:

我无法验证这是否有效,但我在另一个问题中看到您使用选项PDO::ATTR_TIMEOUT 来强制设置更高的超时时间。我不确定默认设置是什么。

'sqlsrv' => [
    'driver'   => 'sqlsrv',
    'host'     => env('DB_HOST', 'localhost'),
    'database' => env('DB_DATABASE', 'forge'),
    'username' => env('DB_USERNAME', 'forge'),
    'password' => env('DB_PASSWORD', ''),
    'charset'  => 'utf8',
    'prefix'   => '',
    'options' => [
        PDO::ATTR_TIMEOUT => 240  // 240 seconds.
    ]
],

您可能还想看看Can I set a query timeout when using Zend_Db_Adapter_Pdo_Mssql?。

【讨论】:

谢谢,马上试试,我会回复你的。 完美,非常感谢。如此晦涩难懂,那个帖子(你从哪里得到修复)甚至不是相同的错误代码,但它有效!非常感谢。

以上是关于SQL Server 随机超时问题的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 代理作业超时

SQL Server 的超时设置

SQL Server 简单插入语句超时

在 SQL Server 中强制查询超时

SQL Server 调查超时错误

SQL Server超时诊断