SQL Server随机超时问题

时间:2016-12-08 19:49:49

标签: php sql sql-server laravel

你好

我目前正在尝试运行一个处理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 chunk,我可以插入~50k记录而不会发生任何事故:

$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?),我可能不得不提高数据库的超时限制

任何事情都有帮助,提前谢谢!

2 个答案:

答案 0 :(得分:3)

我无法验证这是否有效,但我在另一个问题中看到您使用选项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?

答案 1 :(得分:1)

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

如果您正在离开SQL Server,Oracle也有job scheduler,但我并不熟悉它。

由于您表示您计划在某个时候将逻辑移出SQL Server,一旦您有时间可能(如果您碰巧使用的是Windows服务器,我强烈推荐这一点,因为我拥有Microsoft stock :))是编写一个控制台应用程序并使用Windows Task Scheduler按照您选择的计划运行它。您甚至可以在后台运行它而无需打开控制台窗口。