处理数据库离线 1 分钟以更新查询
Handling database going offline for 1 minute to update in query
供应商提供了一个只读的 MS SQL 数据库,我们使用 PHP 与之交互。
该数据库在我们的时间上午 630 点和上午 1230 点更新数据。这会导致数据库离线不到一分钟,但这对于 运行 命中它的 cronjobs 来说已经足够了,而且最终用户偶尔也会命中离线数据库。
日志显示错误是连接错误:
Cannot open user default database. Login failed. (severity 11)
General SQL Server error: Check messages from the SQL Server (severity 11)
Login failed for user 'USER'. (severity 14)
General SQL Server error: Check messages from the SQL Server (severity 14)
Unable to connect to server: SERVER
如果服务器在操作过程中出现故障,而不是与数据库的连接出现故障,则日志会显示以下错误:
The SELECT permission was denied on the object 'TABLE', database 'DATABASE', schema 'dbo'. (severity 14)
General SQL Server error: Check messages from the SQL Server (severity 14)
Query failed
处理此问题的最佳方法是什么?查询和连接与 "or die" 停止处理配对。最好抛出 sleep(60) 暂停执行一分钟并重试 query/connection 吗?这是当前的例子。该连接来自页面开头的共享 require_once 包含,因此在查询之前通常会发生一些其他操作。
$mslink = mssql_connect('SERVER', 'USER', 'PASS');
if (!$mslink || !mssql_select_db('TABLE', $mslink)) {
die('Unable to connect or select database!');
}
$strSQL = "SELECT X,Y,Z FROM TABLE WHERE FOO = 'BAR'";
$objQuery = mssql_query($strSQL) or die("Error Query [" . $strSQL . "]");
我考虑过检测时间并在连接之前延迟它(这应该意味着查询会没问题),或者让它失败然后休眠并重试(这似乎是一个更糟糕的主意 - 因为它' d 导致日志条目)。
这是 try/catch 而不是使用 if true 功能的好地方吗?我之前没有用 try/catch 做过任何事情。
我希望有连接的解决方案是最简单的,因为与每次查询都进行更改相比,只需更改一次即可覆盖代码库。没有框架或任何东西,这是直接 PHP (和程序,我知道,请温柔)。计划是在将来某个时候从 ext\mssql 转移到 PDO。
我想出了一个我满意的答案。知道服务器每六个小时最多离线一分钟,我发现连接失败然后睡了几秒钟直到重试,等待 60 秒的上限。这非常有效,并开始 return 更好地了解其他服务器在更新期间不可用的时间。
我还从 MSSQL(在 PHP7 中弃用)切换到 PDO 和 SQLSRV。下面的代码适用于 SQLSRV,因为它是我最初问题的最接近替代品。
此代码与连接详细信息一起存储,因此不需要在每次查询尝试时都出现,只需在连接时的主要包含中。
$mslink = sqlsrv_connect($serverName, $connectionOptions);
if (!$mslink) {
$ms_sql_errors = sqlsrv_errors();
if ($ms_sql_errors[0]['SQLSTATE'] == 42000) { // This is the database update error
error_log("Cannot open database at $serverName", 0);
} elseif ($ms_sql_errors[0]['SQLSTATE'] == "HYT00") {
error_log("Timeout - is the address $serverName correct?", 0);
} elseif ($ms_sql_errors[0]['SQLSTATE'] == 28000) {
error_log("Login Failed!", 0);
} elseif ($ms_sql_errors[0]['SQLSTATE'] == "08001") {
error_log("Network error connecting to $serverName", 0);
} else {
error_log($ms_sql_errors[0]['SQLSTATE'], 0);
}
while (!$mslink && $failcount < 6) {
$failcount++;
sleep(10); // Attempt to reconnect after $serverName disappears
$mslink = sqlsrv_connect($serverName, $connectionOptions);
if (!$mslink) {
error_log("$serverName retry $failcount failed to connect after a 10 second sleep!, will wait 10 seconds and try again...", 0);
if ($failcount >= 6) {
error_log("$serverName connection FAILED AFTER $failcount 10 second sleeps, stopping", 0);
}
} else {
error_log("DW connection worked after $failcount 10 second sleep(s)", 0);
}
}
}
我希望这可以帮助那些不想做太多跑腿工作来应对已知和预期的 SQL 服务短暂访问的人。
供应商提供了一个只读的 MS SQL 数据库,我们使用 PHP 与之交互。
该数据库在我们的时间上午 630 点和上午 1230 点更新数据。这会导致数据库离线不到一分钟,但这对于 运行 命中它的 cronjobs 来说已经足够了,而且最终用户偶尔也会命中离线数据库。
日志显示错误是连接错误:
Cannot open user default database. Login failed. (severity 11)
General SQL Server error: Check messages from the SQL Server (severity 11)
Login failed for user 'USER'. (severity 14)
General SQL Server error: Check messages from the SQL Server (severity 14)
Unable to connect to server: SERVER
如果服务器在操作过程中出现故障,而不是与数据库的连接出现故障,则日志会显示以下错误:
The SELECT permission was denied on the object 'TABLE', database 'DATABASE', schema 'dbo'. (severity 14)
General SQL Server error: Check messages from the SQL Server (severity 14)
Query failed
处理此问题的最佳方法是什么?查询和连接与 "or die" 停止处理配对。最好抛出 sleep(60) 暂停执行一分钟并重试 query/connection 吗?这是当前的例子。该连接来自页面开头的共享 require_once 包含,因此在查询之前通常会发生一些其他操作。
$mslink = mssql_connect('SERVER', 'USER', 'PASS');
if (!$mslink || !mssql_select_db('TABLE', $mslink)) {
die('Unable to connect or select database!');
}
$strSQL = "SELECT X,Y,Z FROM TABLE WHERE FOO = 'BAR'";
$objQuery = mssql_query($strSQL) or die("Error Query [" . $strSQL . "]");
我考虑过检测时间并在连接之前延迟它(这应该意味着查询会没问题),或者让它失败然后休眠并重试(这似乎是一个更糟糕的主意 - 因为它' d 导致日志条目)。
这是 try/catch 而不是使用 if true 功能的好地方吗?我之前没有用 try/catch 做过任何事情。
我希望有连接的解决方案是最简单的,因为与每次查询都进行更改相比,只需更改一次即可覆盖代码库。没有框架或任何东西,这是直接 PHP (和程序,我知道,请温柔)。计划是在将来某个时候从 ext\mssql 转移到 PDO。
我想出了一个我满意的答案。知道服务器每六个小时最多离线一分钟,我发现连接失败然后睡了几秒钟直到重试,等待 60 秒的上限。这非常有效,并开始 return 更好地了解其他服务器在更新期间不可用的时间。
我还从 MSSQL(在 PHP7 中弃用)切换到 PDO 和 SQLSRV。下面的代码适用于 SQLSRV,因为它是我最初问题的最接近替代品。
此代码与连接详细信息一起存储,因此不需要在每次查询尝试时都出现,只需在连接时的主要包含中。
$mslink = sqlsrv_connect($serverName, $connectionOptions);
if (!$mslink) {
$ms_sql_errors = sqlsrv_errors();
if ($ms_sql_errors[0]['SQLSTATE'] == 42000) { // This is the database update error
error_log("Cannot open database at $serverName", 0);
} elseif ($ms_sql_errors[0]['SQLSTATE'] == "HYT00") {
error_log("Timeout - is the address $serverName correct?", 0);
} elseif ($ms_sql_errors[0]['SQLSTATE'] == 28000) {
error_log("Login Failed!", 0);
} elseif ($ms_sql_errors[0]['SQLSTATE'] == "08001") {
error_log("Network error connecting to $serverName", 0);
} else {
error_log($ms_sql_errors[0]['SQLSTATE'], 0);
}
while (!$mslink && $failcount < 6) {
$failcount++;
sleep(10); // Attempt to reconnect after $serverName disappears
$mslink = sqlsrv_connect($serverName, $connectionOptions);
if (!$mslink) {
error_log("$serverName retry $failcount failed to connect after a 10 second sleep!, will wait 10 seconds and try again...", 0);
if ($failcount >= 6) {
error_log("$serverName connection FAILED AFTER $failcount 10 second sleeps, stopping", 0);
}
} else {
error_log("DW connection worked after $failcount 10 second sleep(s)", 0);
}
}
}
我希望这可以帮助那些不想做太多跑腿工作来应对已知和预期的 SQL 服务短暂访问的人。