假设我有一个函数,用于在某些情况下在数据库中将名为project_id的列递增1。 (假设自动增量不满足此用例,因为在确定是否递增之前必须运行逻辑)。
当用户单击“New Project”时,该函数会在数据库中找到当前最大的project_id,执行SOME OTHER STUFF,并通过将project_id递增1来添加一行。
当多个用户连接时,服务器处理SOME OTHER STUFF所花费的时间是否有可能导致多个用户获取相同的project_id?如果是这样,您将如何避免这个问题?以这种方式增加是一个坏主意吗?
这是一个例子。此示例基于Laravel,但该问题通常适用。
function ReallyLongFunction () {
//figure out what the current max project_id is and increment by 1
$newProjectId = Project::max("project_id")+1;
//Some other stuff that the server has to do. I am exaggerating here the length of time.
//If another user triggers this function, will both users will have the same project id?
sleep(2);
//Insert new row into database
$project = new TempProject;
$project->project_id = $newProjectId;
$project->save();
}
答案 0 :(得分:2)
在自己的代码中执行sql server在内部可以做得更好的事情总是一个坏主意。 $newProjectId = Project::max("project_id")+1;
听起来非常像auto_increment的替代品。但是,如果您的要求比这更复杂,则需要locks
[LOW_PRIORITY] WRITE锁定:
持有锁的会话可以读写表。
只有持有锁的会话才能访问该表。没有其他 会话可以访问它,直到锁被释放。
在写入时,其他会话阻止对表的请求 锁定。
如果WRITE锁定,LOW_PRIORITY修饰符会影响锁定调度 请求必须等待,如稍后所述。
如果LOCK TABLES语句由于其他人持有的锁而必须等待 在任何表上的会话,它会阻塞直到所有锁都可以 获得的。
如果很多用户同时访问同一页面,响应将开始变慢,因为第二个请求在第一个请求完成之前无法提供。