mysqli_begin_transaction($conn);
$sql = "UPDATE foldertable SET trashed = 1 WHERE serverToken = (SELECT serverToken from servertoken where userToken = ? limit 1) and
(folderId = ?
or
RootFolderPath LIKE
CONCAT (
(SELECT RootFolderPath FROM foldertable WHERE serverToken = (SELECT serverToken from servertoken where userToken = ? ) AND folderid = ? limit 1)
,'/'
, ?
,'%'
)
)";
$stmt = mysqli_stmt_init($conn);
mysqli_stmt_prepare($stmt, $sql);
mysqli_stmt_bind_param($stmt, "sisii", $data["userToken"], $id, $data["userToken"], $id, $id);
if (!mysqli_stmt_execute($stmt)) {
echo mysqli_stmt_error($stmt);
$serverError = true;
return;
}
// echo "\n\n affected rows " . mysqli_affected_rows($conn);
if (mysqli_affected_rows($conn) > 0) {
sleep(15);
// Insert into bin folder
$sql = "INSERT INTO binfolder (serverToken , folderId) value ( (SELECT serverToken from servertoken where userToken = ? limit 1) , ?)";
$stmt = mysqli_stmt_init($conn);
mysqli_stmt_prepare($stmt, $sql);
mysqli_stmt_bind_param($stmt, "si", $data["userToken"], $id);
if (!mysqli_stmt_execute($stmt)) {
echo mysqli_stmt_error($stmt);
$serverError = true;
return;
}
if (mysqli_affected_rows($conn) > 0) {
$success = true;
mysqli_commit($conn);
}
}
INSERT INTO foldertable(serverToken) SELECT (123456)
如果在事务启动后执行insert查询,但插入不必等待事务完成。因为事务的update查询确实锁定了insert查询所涉及的行。
如果Insert查询不包含插入查询中所需的相同serverToken
,则插入查询将立即运行。
提前谢谢你。
发布于 2021-05-11 09:10:41
对于事务阻塞,第一道防线是加快查询速度。虽然这并不能完全消除阻塞/延迟/死锁的可能,但它通常会使这种情况更容易容忍。
是LIMIT 1
吗?--只有一个吗?如果是这样的话,为什么不做一个JOIN
。或者可能有不止一个?如果是,是哪一个?也就是说,你不需要一个ORDER BY
吗?
servertoken
需要INDEX(userToken, serverToken)
一个INSERT ... ON DUPLICATE KEY UPDATE ...
是否足以满足您冗长的查询集?如果是这样的话,它可能会快得多。
我在long查询中看到一个OR
。这可能会阻止索引的使用。(我不太理解这个查询的意图,无法提出一个替代方案。)
"RootFolderPath喜欢CONCAT (.“) --这闻起来像是应该重新设计的东西。考虑将路径部分放在单独的列中吗?或者别的什么。
folderId
是PRIMARY KEY
of folderTable
吗?
请为每个相关表提供SHOW CREATE TABLE
(作为文本,而不是图像)。
https://dba.stackexchange.com/questions/291347
复制