【问题标题】:Pdo 3, multiple runnings: error: 17 database schema has changedpdo 3,多次运行:错误:17 数据库架构已更改
【发布时间】:2014-12-26 16:57:39
【问题描述】:

我有这个测试代码:

session_start();
session_write_close();
set_time_limit(0);

for ($i = 1; $i < 1000; $i++)
{
    if (rand(1,5) == 1)
    {
        $file_db = new PDO('sqlite:x.db');
        $file_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $file_db->exec('DROP TABLE IF EXISTS messages');
        $file_db = null;
    }
    $file_db = new PDO('sqlite:x.db');
    $file_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $file_db->exec('CREATE TABLE IF NOT EXISTS messages (id INTEGER PRIMARY KEY AUTOINCREMENT,title TEXT,message TEXT,time INTEGER)');
    $file_db->query('INSERT INTO messages VALUES (null, "'.rand(1,9999).'", "'.rand(1,99).'", date("now"))');
    $file_db = null;
}

$file_db = new PDO('sqlite:x.db');
$file_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$i = 0;
foreach ($file_db->query('SELECT * FROM messages') as $m)
{
    $i++;
    echo $i.' -> '.$m['id'].'<br>';
}

我使用此代码测试 PDO 3 是否适用于多个并发。如果此代码在一个线程中运行,则一切正常。但是,一旦我启动了两个实例,我就会收到以下消息:

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 17 database schema has changed' in code.php:* Stack trace: #0 code.php(*): PDO->query('INSERT INTO mes...') #1 {main} thrown in code.php on line *

错误行是 INSERT INTO 所在的位置。为什么会发生这种情况以及如何躲避它? (我正在创建一个缓存系统,其中有可能创建和删除表。我知道有 TRUNCATE,我只想知道为什么会发生这种情况)

【问题讨论】:

  • 如果您使用 SQLite,为什么要将此标记为 mysql

标签: php sqlite pdo


【解决方案1】:

[...] 启动两个实例后,我收到以下消息: [...] SQLSTATE[HY000]: General error: 17 database schema has changed [...] 为什么会发生这种情况以及如何躲避它?

Sqlite 是一个单文件数据库。您并行打开它,然后更改数据库结构。在您刚刚删除要插入的表格时插入数据只是不起作用,因为表格已经消失。这就解释了为什么会发生这种情况。

希望您现在已经了解无法插入到不存在的表中,解决方案可能很明显:仅插入到现有表中。

为确保在删除表后创建表,在事务中执行此类操作可能会有所帮助:https://www.sqlite.org/lang_transaction.html

【讨论】:

  • 是的,现在我明白了。在“CREATE TABLE IF NOT EXISTS 消息”和“INSERT INTO 消息 VALUES (null,” 是的,表可以被其他线程删除,所以现在合理
  • 所以,开始一个事务,然后删除表,然后重新创建它并提交事务。那么当你插入时,一个表应该总是存在的。
【解决方案2】:

尝试
$file_db = new PDO(realpath('sqlite:x.db')); 对于
$file_db = new PDO('sqlite:x.db');

【讨论】:

    猜你喜欢
    • 2017-05-11
    • 1970-01-01
    • 2023-03-31
    • 2017-01-14
    • 2017-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多