MySQL扩展已过时,将来会被移除:请改用mysqli或PDO。

176

当我试图从PHP连接到MySQL服务器时,我会看到以下错误:

已弃用:mysql扩展已被弃用,并将在未来被移除:请改用mysqli或PDO代替,在/path/to/filename.php的第123行。

参考行的代码是:

mysql_connect($server, $username, $password);

我确信这些论点是正确的,而且这段代码多年来一直没有问题。事实上,我是从一个关于PHP的权威教程中获得了它。

  1. 为什么会发生这种情况?

  2. 我该如何修复它?

  3. 我知道可以通过将 php.ini 中的 error_reporting 设置为排除 E_DEPRECATED 来抑制过时错误:

error_reporting = E_ALL ^ E_DEPRECATED

如果我这样做会发生什么?


1
这里有一个用于将MySQL转换为MySQLi的源代码扫描工具:Converting to MySQLi (Dec 2011; by Keith Larson; Oracle Mysql Wiki) - hakre
5
使用pdo_query()函数。它是从mysql_最简单的升级路径,并使用PDO,这是两个选择中更友好的一个。MYSQLI实际上只是一个临时API;初学者因其名称相似而感到诱人,但由于函数签名的变化需要更多重写,即使进行参数化查询也需要更多努力。 - mario
回答问题标题 - PDO更通用,一般来说它是更好的解决方案。@DennisDegryse => 尽管我更喜欢面向对象的PDO,但MySQLi也有一种面向对象的使用方式(搜索“mysqli类”)。更多关于PDO | MySQLi的比较,请参见http://code.tutsplus.com/tutorials/pdo-vs-mysqli-which-should-you-use--net-24059和http://php.net/manual/en/mysqli.overview.php。 - jave.web
在上面的链接所评论的Oracle MySQL Wiki中找不到任何内容。 - David Augustus
1
@hakre 感谢您提供的工具链接。作为一般性评论,请注意并非所有命令都可以简单地将 mysql_ 转换为 mysqli_,因为它们的功能是不同的。 - user1239087
1个回答

188
  1. Why is this happening?

    The entire ext/mysql PHP extension, which provides all functions named with the prefix mysql_, was officially deprecated in PHP v5.5.0 and removed in PHP v7.

    It was originally introduced in PHP v2.0 (November 1997) for MySQL v3.20, and no new features have been added since 2006. Coupled with the lack of new features are difficulties in maintaining such old code amidst complex security vulnerabilities.

    The manual has contained warnings against its use in new code since June 2011.

  2. How can I fix it?

    As the error message suggests, there are two other MySQL extensions that you can consider: MySQLi and PDO_MySQL, either of which can be used instead of ext/mysql. Both have been in PHP core since v5.0, so if you're using a version that is throwing these deprecation errors then you can almost certainly just start using them right away—i.e. without any installation effort.

    They differ slightly, but offer a number of advantages over the old extension including API support for transactions, stored procedures and prepared statements (thereby providing the best way to defeat SQL injection attacks). PHP developer Ulf Wendel has written a thorough comparison of the features.

    Hashphp.org has an excellent tutorial on migrating from ext/mysql to PDO.

  3. I understand that it's possible to suppress deprecation errors by setting error_reporting in php.ini to exclude E_DEPRECATED:

    error_reporting = E_ALL ^ E_DEPRECATED
    

    What will happen if I do that?

    Yes, it is possible to suppress such error messages and continue using the old ext/mysql extension for the time being. But you really shouldn't do this—this is a final warning from the developers that the extension may not be bundled with future versions of PHP (indeed, as already mentioned, it has been removed from PHP v7). Instead, you should take this opportunity to migrate your application now, before it's too late.

    Note also that this technique will suppress all E_DEPRECATED messages, not just those to do with the ext/mysql extension: therefore you may be unaware of other upcoming changes to PHP that would affect your application code. It is, of course, possible to only suppress errors that arise on the expression at issue by using PHP's error control operator—i.e. prepending the relevant line with @—however this will suppress all errors raised by that expression, not just E_DEPRECATED ones.


你应该做什么?

  • 您正在启动一个新项目。

    没有绝对的理由使用ext/mysql, 选择其他更现代的扩展,并获得其提供的好处。

  • 您有(自己的)遗留代码库依赖于ext/mysql

    执行回归测试是明智的:在确定所有潜在影响领域、计划每个领域并在分期环境中充分测试解决方案之前,您真的不应该改变任何东西(特别是升级PHP)。

    • 遵循良好编码实践,您的应用程序以松散集成/模块化方式开发,数据库访问方法都是自包含的,可以轻松地被新扩展替换。

      花费半小时重写此模块以使用其他更现代的扩展;进行全面测试。然后,您可以引入进一步的改进以获得其提供的好处。

    • 数据库访问方法分散在各个地方,无法轻松地被新扩展替换。

      考虑是否真的需要此时升级到PHP v5.5。

      您应该开始计划使用其他更现代的扩展替换ext/mysql,以便获得其提供的好处;您还可以将其用作重构数据库访问方法成更模块化结构的机会。

      但是,如果您急需立即升级PHP,您可能需要暂时禁止弃用错误:但首先请确保标识出任何其他被抛出的弃用错误。

  • 您正在使用依赖于ext/mysql的第三方项目。

    考虑是否真的需要此时升级到PHP v5.5。

    检查开发人员是否发布了与此特定问题相关的修复、解决方法或指导; 如果没有,请通过引起他们的注意来迫使他们这样做。如果您急需立即升级PHP,则可以考虑暂时禁止弃用错误:但首先请确保标识出任何其他被抛出的弃用错误。

    执行回归测试绝对是必要的。


4
请建议使用预处理语句,因为我经常看到用户以与MySQL相同的方式使用PDO或mysqli查询,即使他们没有转义单引号,这更加危险。 - NullPoiиteя
4
@NullPointer说:“它已经说了‘他们...提供...准备好的语句(从而提供了最佳方法来击败SQL注入攻击)’。我不想在这个答案中举例参数化查询,因为它与手头的问题没有什么关系;你认为如何使其更清晰?” - eggyal
3
如果您想要一个快速且简单的解决方法,只需在mysql_connect之前加上@符号即可抑制它。例如:@mysql_connect(...); 这样做,您无需更改任何其他配置。使用其余的mysql_函数是可以的,只有mysql_connect()会出现此消息。 - Bimal Poudel
我在我的项目中使用mysql_real_escape_string(),没有数据库(主要是为了防止来自用户生成的标题等的“跟读攻击”)。很遗憾,这个函数已经消失了。事实上,“参数化查询不需要它”并没有真正帮助到我。 - Frank N
2
@FranKee:如果不是在数据库中存储这些用户生成的标题,那么您将它们存储在哪里?您提到的“跟我说话”攻击是什么?在没有MySQL数据库的情况下使用mysql_real_escape_string() 绝对不是 战胜任何东西的正确方法(因为它根据您的MySQL数据库连接的字符集转义字符串,而您没有这个!)。如果您正在尝试防止XSS攻击,则应该使用htmlentities()。对于任何其他攻击,请详细说明确切的威胁。 - eggyal
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接