mysql - Laravel 4 独家事务更新和选择

标签 mysql sql sqlite transactions laravel

我需要从设置为空闲的 SQLite 数据库中选择一行,然后将该行标记为已使用。至关重要的是,选择和更新是一个原子操作,并且不存在两个用户将同一行返回为空闲的风险。

不幸的是,Laravel 在调用 DB::transaction 时似乎没有提供事务类型的选择,如果我将它作为 DB::statement 运行,那么我不会获得返回值。

此外,由于 SQLite 不支持变量,我无法在选择和更新之间存储主键,所以我不确定是否可以在 SQLite 数据库之外运行它。

可以使用 Laravel 和 SQLite 吗?

如果不是,那么我需要将下一个空闲 ID 存储在与 SQLite 数据库相关的 MySQL 表中,并改为对该行使用锁定。在 MySQL 中按行锁定有什么主要的语法差异吗? (我不能不小心锁住整个表)

我正在寻找与此类似的语法:(当然 SQLite 不支持变量除外)

BEGIN EXCLUSIVE TRANSACTION
  SET @free = SELECT InternalID FROM main WHERE Called = 0 LIMIT 1;
  UPDATE main SET Called = 1 WHERE InternalID = @free;
  SELECT * FROM main LEFT JOIN lead ON main.InternalID = lead.InternalID WHERE main.InternalID = @free;
END TRANSACTION

因为我确定有人会问“为什么要使用两个数据库系统!?!”:

SQLite 数据库包含需要灵活列数的数据。这些数据将在几个月内每周使用几天,然后可以存档。需要有相当多的这些“迷你数据库”。这些数据不能有效地存储在 MySQL 中(我要替换的以前的系统试过这个,但它变得非常慢)。每个 SQLite 数据库的并发性都非常低,但至关重要的是绝对不可能有两个用户获得相同的行——这在旧系统中发生过几次。

最佳答案

我会忘记尝试锁定表和/或在事务中执行此操作,对此有更好的模式:

  • 生成唯一 token
  • 将该 token 分配给下一条可用记录
  • 读取哪一行得到了token,并处理

那样你根本不需要锁定和交易(因为数据库只会将你的 token 分配给一个未使用的记录)。

伪代码:

$token = time(); //Only you have very low concurrency. Otherwise use something more unique, like a GUID or an identity value from a tokens table.

EXEC SQL: "UPDATE mytable SET token = $token WHERE token IS NULL LIMIT 1"

EXEC SQL: "SELECT id FROM mytable WHERE token = $token"

process($id);

关于mysql - Laravel 4 独家事务更新和选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17180818/

相关文章:

android - 对 SQLite 数据库的 Activity 和后台服务访问

mysql - 错误代码 : 1267. 操作 '=' 的排序规则 (utf8_general_ci,IMPLICIT) 和 (utf8_unicode_ci,IMPLICIT) 的非法混合

mysql - 仅当两个或多个记录具有相同值时才连接两个表并分组

java - 是什么导致了这个 SQLException?

c# - 无法访问 SQLite 数据库窗体窗口服务

python - 有没有办法从 python 异步或并行运行 SQLite 查询?

mysql - 为什么不正确地命令 asc?

python - 1045, "Access denied for user ' 用户名'@'NOT-local' (使用密码: YES)"

sql - 触发错误时回滚事务

php - mysql 根据 LEAST 值返回正确的链接