Laravel 4独家交易,更新和选择

时间:2013-06-18 23:50:17

标签: mysql sql sqlite transactions laravel

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

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

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

是否可以使用Laravel和SQLite?

如果没有,那么我将需要在MySQL表中存储与SQLite数据库相关的下一个空闲ID,并在该行上使用锁定。在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 dbs包含需要灵活列数的数据。这些数据将每周使用几天,持续数月,然后可以存档。需要相当多的这些“迷你数据库”。这些数据无法有效地存储在MySQL中(之前我正在替换的系统试过这个,而且速度非常慢)。每个SQLite数据库的并发性都很低,但至关重要的是两个用户绝对没有机会获得同一行 - 这在旧系统中发生了几次。

1 个答案:

答案 0 :(得分:2)

我忘了试图锁定表和/或在事务中执行它,有更好的模式:

  • 生成唯一令牌
  • 将该令牌分配给下一个可用记录
  • 读取哪一行获得了令牌并进行处理

这样你根本不需要锁定和事务(因为数据库只会将你的令牌分配给一个未使用的记录)。

的伪代码:

$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);
相关问题