多线程单连接中的 PDO::lastInsertId() 是不是安全?

Posted

技术标签:

【中文标题】多线程单连接中的 PDO::lastInsertId() 是不是安全?【英文标题】:Is PDO::lastInsertId() in multithread single connection safe?多线程单连接中的 PDO::lastInsertId() 是否安全? 【发布时间】:2019-07-14 10:23:07 【问题描述】:

我在这里阅读了一些关于PDO::lastInsertId() 及其安全性的帖子。它从当前连接返回最后插入的 ID(因此对于多用户应用程序来说是安全的,而每个用户/脚本运行只有一个连接)。

我只是想知道如果多核服务器系统中每个长脚本(大量 SQL 请求)只有一个数据库连接,是否有可能获得无效 ID?这个问题更有可能是理论上的。

我认为 php 脚本运行是线性的,但也许我错了。

【问题讨论】:

PHP 不是多线程的。你什么意思?你有什么问题吗? @Dharman 这更多是关于 PDO 中支持的数据库,而不是关于 PHP。问题是关于多核心,而你是在谈论多线程,它们是不一样的。在几乎所有情况下,操作系统都会为任何正在运行的进程抽象内核。硬件具有一个核心或多个核心基本上都没有关系,操作系统将处理相同的进程。因此,内核的数量与 PDO 无关。 @Dharman 我正在更新我的 PDO 包装类,我需要使用 lastInsertId。起初我想知道多用户应用程序是否安全,我在这里找到了答案,即每个连接都是安全的。我的应用程序为每个用户创建一个连接(对于许多请求),所以我只是对任何可能的问题感到好奇(每个连接有很多请求是否安全?)。如果一个脚本运行是线性的,而不是神奇的多线程,它往往是安全的。 【参考方案1】:

PDO 本身不是线程安全的。如果您使用来自线程应用程序的 PDO 连接,则必须提供自己的线程安全性。

最好的也是我认为唯一可维护的方法是使您的连接线程私有。

如果您尝试使用来自多个线程的一个连接,您的 mysql 服务器可能会抛出 Packet Out of Order 错误。

最后插入 ID 功能可确保与 MySQL 的多个连接获得自己的 ID 值,即使多个连接对同一个表执行插入操作。

对于典型的 php Web 应用程序,使用多核服务器可以处理更多的 Web 浏览器请求。多核服务器不会使 php 程序多线程。每个 php 程序,为了处理每个 web 请求,都分配了自己的 PDO 连接。正如您所说,每个 php 脚本运行都是“线性的”。多核允许多个脚本同时运行,但独立运行。

Last Insert ID 旨在确保该场景的安全性。

在某些情况下,一个 php 程序可能会在完成后让 MySQL 连接保持打开状态,以便另一个 php 程序可以使用它。这称为持久连接或连接池。当网站有许多用户连接到它时,它有助于提高性能。可重用连接的通用术语是“串行可重用资源。*

一些 php 程序可能使用线程。在这种情况下,程序必须避免允许多个线程同时使用同一个连接,否则会出现可怕的 Packet Out of Order 错误。

(几乎所有机器都有多个内核。)

【讨论】:

我很困惑。我听说过多线程 PHP,但我一直认为您需要一些用 C 编写的非官方第三方库,例如 pthreads。使用常规 PHP,物理上是否有可能让两个 PHP 进程同时共享同一个数据库会话(与重用由前一个但已经死的进程启动的持久连接相比)? 多线程,请看我编辑的答案。在多个线程之间共享连接,后果自负。持久连接,请参阅我编辑的答案。当您编写 两个 PHP 进程时,我相信您的意思是 两个 PHP 线程。

以上是关于多线程单连接中的 PDO::lastInsertId() 是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章

Java千百问_02基本使用(012)_如何编写多线程Socket程序

Redis 6 中的多线程是如何实现的!?

c#中Timer是单线程还是多线程

Redis单线程解读

redis单线程如何支持高并发

redis单线程如何支持高并发