【问题标题】:Sqlite3, SQLSTATE[HY000]: General error: 5 database is lockedSqlite3, SQLSTATE[HY000]: 一般错误: 5 数据库被锁定
【发布时间】:2015-01-12 13:14:58
【问题描述】:

我有这个小测试脚本:

session_start();
session_write_close();
error_reporting(-1);
register_shutdown_function(function() {
    //echo 'shutdown';
});

$MAX = 120;
set_time_limit($MAX);
echo date('Y-m-d H:i:s').'<br>';
$m = microtime(true);
$file_db = new PDO('sqlite:'.dirname(__FILE__).'/test.sqlite3');
$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)");

$d = date('U');
do
{
    $file_db->exec ('INSERT INTO messages VALUES (null, "titleee'.rand(1,9).'", "MESSAGEEEE'.rand(1,99).'", "'.rand(1,999).'")');
    if (date('U') - $d > $MAX/2)
    {
        break;
    }
} while (true);
$file_db = null;
echo 'ok: '.(microtime(true)-$m);

如果这是在多个实例的浏览器中运行,迟早它会丢弃“SQLSTATE [HY000]:一般错误:5 数据库被锁定”异常。怎么躲?

【问题讨论】:

  • $file_db-&gt;exec 之后添加:sleep(2) 太多进程试图太快地插入到锁定表的数据库中。
  • 嗯,不能设置成“挂断”直到它没有被锁定吗?
  • 从未使用过,但欢迎您在实例化$file_db 后立即尝试:$file_db-&gt;query("SET LOCK MODE TO WAIT 120")。这应该使脚本最多等待两分钟才能解锁表...
  • 我建议您在下面的答案中检查是否有未保存的更改。如果这样可以解决问题,并且如果它与需要的一样精确,请选择它作为此问题的答案。

标签: php sqlite


【解决方案1】:

我有这个错误是因为我在 SQLiteBrowser 上有一条未保存的记录,然后 SQLite 不会在上面写。保存记录后,我的脚本恢复正常工作。因此,每次发生此错误时,请检查您的 SQLiteBrowser(或任何其他编辑器)是否已打开并且是否有任何未保存的更改。

【讨论】:

    【解决方案2】:

    $file_db-&gt;exec 之后添加:sleep(2) 太多进程试图太快地插入到锁定表的数据库中。欢迎您在实例化$file_db 后立即尝试:$file_db-&gt;query("SET LOCK MODE TO WAIT 120")。这应该使脚本最多等待两分钟以解锁表...

    【讨论】:

    • 我添加了“$file_db->setAttribute(PDO::ATTR_TIMEOUT, 0);”我发现了异常。如果发生该异常,我只需再次运行该查询+我执行“usleep” - 这在理论上可行,不是吗?
    • 是的,理论上这可以正常工作,尽管您可能希望从睡眠开始以稍微抵消尝试...
    • 切换到 mysql 将允许您像这样使用延迟关键字:INSERT DELAYED INTO ...,它提供并发数据库插入。
    • 使用后关闭光标:$stmt->closeCursor();
    【解决方案3】:

    我跟踪到了虚拟机网络文件共享问题的锁定问题:https://www.sqlite.org/lockingv3.html#how_to_corrupt

    应该注意,已知 POSIX 咨询锁定在许多 NFS 实现(包括最新版本的 Mac OS X)上存在错误甚至未实现,并且有报告称 Windows 下的网络文件系统存在锁定问题。您最好的防御措施是不要将 SQLite 用于网络文件系统上的文件。

    我能够通过将 SQLite 数据库文件移动到未与主机操作系统安装/共享的来宾操作系统 (Linux) 目录来解决此问题(Windows)

    在我的例子中,我将 SQLite 数据库文件移动到 Linux 来宾操作系统上的 /tmp

    【讨论】:

      猜你喜欢
      • 2012-10-24
      • 2012-10-25
      • 2014-12-31
      • 1970-01-01
      • 2021-09-10
      • 1970-01-01
      • 2011-03-03
      • 2013-06-20
      相关资源
      最近更新 更多