15

我知道 PHP 的mysql_*函数已被弃用,我不应该使用它们

然而,我们有几个遗留的 MySQL 4.0 数据库,无论是函数mysqli_*还是PDO函数都不支持连接到这些数据库。继续使用最新的 PHP 版本并仍然能够连接到这些数据库的最佳方法是什么?

(根据 PDO 介绍页面顶部的描述,我最初认为 PDO 可能是一个选项,但页面下方的变更日志表明 PHP 5.4 已放弃对 pre-4.1 的支持)

我知道 MySQL 4.0 已经 10 年了,这里真正的问题是我们仍在使用它。升级 MySQL 是一个单独的问题,超出了我的影响范围和这个问题的范围。我可以控制的是我们使用的 PHP 版本——我不想仅仅因为我们需要连接到一些旧的数据库而不得不停止升级 PHP。

甚至 PDO 也将不再连接到这些旧的 MySQL 服务器。

我还应该澄清一下,我们有几个遗留应用程序访问这些数据库,我们希望尽可能少地更改这些应用程序。他们没有进行积极的开发,并且测试涉及重写大部分代码的更改将很快膨胀成一个相当大的 QA 项目。

出于这个原因,重写代码或升级 MySQL 版本等侵入性解决方案不太可能是值得的。如果它们是唯一可用的解决方案,我们可能最终什么都不做 -mysql_*尽可能长时间地使用,然后在最新的 PHP 无法再连接时立即冻结 PHP 版本(至少对于这些应用程序)。

另一方面,技术上复杂的解决方案(例如从头开始编译)绝对是可能的,并且实际上比进行大量代码更改更可取。

4

7 回答 7

11

可以使用 mysql_* 函数或 PDO 从 PHP 5.4 连接到 MySQL 4.0。我刚刚构建了 MySQL 4.0.30 并使用 MySQL Sandbox 启动了它。然后我成功地测试了下面的代码示例。

但是,您不能使用 TCP/IP 协议。

您只能使用 unix 套接字在本地访问 MySQL。使用主机名“localhost”并确保您的 php.ini 已mysql.default_socket为您的 MySQL 实例正确配置。

要使用本地访问方法,您的 PHP 应用程序和数据库服务器必须安装在同一台主机上。

<?php

print "PHP VERSION = " . phpversion() . "\n";

print "\nTEST DEPRECATED EXT/MYSQL:\n";
mysql_connect('localhost', 'msandbox', 'msandbox');
$result = mysql_query("SELECT VERSION() AS 'MySQL VERSION'");
while ($row = mysql_fetch_assoc($result)) {
  print_r($row);
}

print "\nTEST PDO_MYSQL:\n";
try {
  $dbh = new PDO('mysql:host=localhost', 'msandbox', 'msandbox');
  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch(PDOException $err) {
  die($err->getMessage());
}

$stmt = $dbh->prepare("SELECT VERSION() AS 'MySQL VERSION'");
$result = $stmt->execute();
foreach ($stmt->fetchAll() as $row) {
  print_r($row);
}

这是我系统上上述脚本的输出:

PHP VERSION = 5.4.15

TEST DEPRECATED EXT/MYSQL:
Array
(
    [MySQL VERSION] => 4.0.30
)

TEST PDO_MYSQL:
Array
(
    [MySQL VERSION] => 4.0.30
)
于 2013-06-18T02:38:03.297 回答
2

为什么不升级mysql?如果你想要最小的改变,那么升级到 4.1 就足以让 mysqli 运行。我认为这是您应该尝试的第一件事,因为您可以拥有一个测试环境来查看旧应用程序是否适用于 4.1。您还有可能需要检查的 4.1 更改列表,它们位于http://dev.mysql.com/doc/refman/4.1/en/upgrading-from-previous-series.html

如果测试 4.1 暴露了一些问题,那么您将知道需要进行更彻底的更改,并且您需要这些信息来制定策略。我知道你想继续更新 PHP,只是不要留下 mysql 和操作系统。我会在生产中运行 mysql、os 和 php 的稳定组合。当需要继续前进时,构建一个全新的环境。

于 2013-06-18T00:59:59.477 回答
2

遗留的 mysql_* 函数在今天(2013 年 6 月 20 日)发布的 5.5.0 中被删除。我意识到您对这个旧数据库束手无策,但请记住,您现在所经历的被称为技术债务,这是一个重要的概念,需要理解并向负责人解释。

我相信您已经知道旧软件(漏洞等)的危险,但显然这也适用于您的 PHP。目前还支持 5.4.x,但一般来说只支持 PHP 最新的 2 个版本,也就是说 5.3.x 即将到期,只支持 5.5.x 和 5.4.x。由于您需要旧版 MySQL,因此您已经在使用受支持的最古老的 PHP,这是一个危险的游戏。

如果您希望找到一些灵丹妙药,我不能说得比这更简单:没有. 您必须做出艰难的选择,支持遗产并为最终的利用敞开心扉,或者在沙子上划清界限,然后说不。我想说的是,在我从事 IT 的所有这些年中,我从未听过任何人(尤其是在业务方面)说他们对保留旧的遗留东西感到多么高兴。

于 2013-06-20T19:43:28.293 回答
1

从 mysql_* 到 PDO 并没有那么糟糕,PDO 起初看起来有点吓人,并且同意,至少对于从查询中检索数据 (IMO) 来说更复杂一些。

一开始可能有点,但应该不会太糟糕,而且除了是当前的两个标准之一之外,它也更安全。

例如,

$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');

mysql_query($sql)

变得

$link = new PDO("mysql:host=localhost;dbname=$dbname", $dbuser, $dbpass);

$statement = $link->prepare($sql);
$statement->execute(values);
于 2013-06-13T23:29:38.367 回答
1

这可能是一个非常简单的解决方案......当您在过时的 MySQL 数据库修订版上运行旧应用程序时......为什么不保持连续性?我假设应用程序托管在您自己维护的服务器上,而不是第三方(网络托管)

我建议做的是使用不同的机器.. 可能是运行 mysql4.0 的虚拟服务器和适合应用程序的 PHP 版本.. 然后将所有旧版迁移到新服务器.. 然后你就不用担心了关于mysql_*功能的移除/折旧..

使用您的主服务器,根据您当前的开发要求继续升级吗?

于 2013-06-17T23:22:36.253 回答
0

这是一个古老的问题,但令人惊讶地相关。答案其实很简单。如果你有一个旧的 mysql 需要从 PHP 的“新”版本中提取数据,只需使用新版本的 MariaDB 设置一个从站。它应该是您迁移过程的一部分。

复制到新版本的 MariaDB,并连接到该从属设备以读取数据(您应该将其设置为只读副本)

于 2021-07-02T06:35:14.927 回答
-1

这个答案是在 OP 认为 PDO 可以连接到 MySQL 4 时编写的。

您可能会做的是使用 PDO 驱动程序重写 mysql 函数,因此您不会更改原始代码。如果我以 Serdnad 给出的示例为例,您可以执行以下操作:

function mysql_connect($dbhost, $dbusr, $dbpass){
  return new PDO("mysql:host=$dbhost;dbname=mydb", $dbuser, $dbpass);
}

function mysql_select_db($db, $link=false){
  // If you were not using the link argument you might use some global instead
  $link->query("USE $db");
  return 1;
}

function mysql_query($sql, $link=false){
  // If you were not using the link argument you might use some global instead
  $statement = $link->prepare($sql);
  return $statement->execute(values);
}

好吧,有很多 mysql_* 函数,但最后你可以通过在源代码中进行简单的正则表达式搜索来找出你真正使用的那些(可能只有几个)。

我认为你必须对一些函数很聪明,比如 mysql_escape_string、mysql_affected_rows 或 mysql_insert_id,但我很确定这是可行的。

如果在重新定义函数时您的扩展仍然处于活动状态,您将收到一个致命错误,您可以通过使用命名空间来避免该错误,这很容易添加到您的代码中。如果您禁用 mysql ext,我认为您可以在不更改原始代码行的情况下实现您的目标。

于 2013-06-17T23:40:01.500 回答