我正在编写一个PHP脚本,用于处理文件并将有关文件的信息插入到数据库中。
具体来说,脚本处理一些信息,然后开始一个事务并将其插入到表中。然后,我使用lastinsertid
来获得刚刚插入行的ID
,并使用该ID
来处理相关文件。当处理完成时(大约需要2-30秒),我在其他表中执行更多的插入操作,并在检查文件处理成功后完成事务。
所以基本上概要是这样的:
START TRANSACTION
INSERT DATA INTO TABLE 1
PROCESS FILE USING INSERT ID (takes 2-30 seconds)
INSERT DATA INTO TABLE 2
INSERT DATA INTO TABLE 3
INSERT DATA INTO TABLE 4
//VERIFY FILE PROCESSING
if ($file_process == true){
COMMIT
}
else{
ROLLBACK
}
我知道由于长时间持有锁的问题,应该避免长事务,但是如果事务只使用插入怎么办?由于插入只锁定正在插入的行,这仍然是一个问题吗?
谁能给我解释一下这种情况下可能出现的"陷阱"?我很确定,如果一个会话的进程花费了很长时间,而另一个会话开始了他们自己的进程,session 1
将不会阻塞session 2
,因为进程只处理插入。如果session 1
失败并且必须回滚,它将不会对session 2
产生任何影响(除了在数据库中,自动递增的主id会有一个间隙,但这无关紧要)
由于插入只锁定正在插入的行,这仍然是一个问题吗?
不总是正确的。如果在details表中插入记录,主记录也会被锁定。如果您有许多关系,那么很难知道究竟锁定了什么,这反过来又可能导致死锁。
如果PHP脚本中数据库插入的运行时间达到30秒,那么您可能会遇到PHP的最大执行时间上限。
您可以通过编程方式更改时间限制来缓解这种情况。
http://php.net/manual/en/function.set-time-limit.php或
你可以修改你的php.ini文件来改变默认值。如果这成为一个问题,我建议只对数据库调用进行修改,这样您就不会让与数据库无关的失控脚本阻塞服务器的资源。
如果您不确定在那里使用事务,我建议您在那里使用new_added_row
额外列,如果出现问题,您只需删除new_added_row=1
列以回滚您的事务。您仍然会获得insert_id,而不使用事务,并且能够回滚更改。如果多个用户将异步执行此操作,则可以考虑使用' session_key extra列来防止删除其他人的插入。