今天,我为我的一个客户发布了一个新应用程序,并且INSERT语句发生了不正常的事情。 在测试过程中,我们没有遇到类似的问题,并且我不确定这是否是由于同时访问大量用户(100个用户)而发生的,还是与其他事情有关。 因此,在1次插入之后,它在数据库表中插入了1条记录,还有其他2-3个重复...我不使用事务,这可以解决此问题吗?下面您可以找到我的代码以及其中包含事务的代码情况下这将是解决方案。 非常感谢您的帮助!
$submit_the_bill = "INSERT INTO bill_status
(`bill_status_bill_id`,`bill_status_username`, `bill_status_phone_number`, `bill_status_status`,`bill_paid`, `deduction`)
VALUES ('".$bill_id."', '".$_SESSION['username']."', '".$_SESSION['phone_number']."','1','0','".$deduction."')";
$submit_the_bill_result = $conn->query($submit_the_bill);
//TRANSACTION STARTS HERE
try {
$conn->autocommit(FALSE);
$submit_the_bill = "INSERT INTO bill_status
(`bill_status_bill_id`,`bill_status_username`, `bill_status_phone_number`, `bill_status_status`,`bill_paid`, `deduction`)
VALUES ('".$bill_id."', '".$_SESSION['username']."', '".$_SESSION['phone_number']."','1','0','".$deduction."')";
$submit_the_bill_result = $conn->query($submit_the_bill);
$conn->commit();
} catch (Exception $e) {
// An exception has been thrown
// We must rollback the transaction
$conn->rollback();
}
这是整页,信息来自具有格式的上一页,并在执行查询并发送电子邮件后转到主页。有什么想法吗?
<?php session_start();
require('include/config.php'); //database connection
require "PHPMailer/PHPMailerAutoload.php";
$bill_id = $_POST['bill_id'];
$user_phone_number = $_POST['user_phone_number'];
$deduction = $_POST['deduction'];
$net_value_hidden = round($_POST['net_value_hidden'],2);
$official_cost_hidden = round($_POST['official_cost_hidden'],2);
$personal_cost_hidden = round($_POST['personal_cost_hidden'],2);
$tax_hidden = round($_POST['tax_hidden'],2);
$total_hidden = round($_POST['total_hidden'],2);
$total_private_price_with_vat = ($personal_cost_hidden/100)*20;
$total_private_price_with_vat = round($total_private_price_with_vat,2);
$total_payable_ammount = round($personal_cost_hidden + $total_private_price_with_vat,2);
if($total_hidden == 0) {$deduction = 4;}
if($deduction == 1) {$deduction_email = "Salary";}
else if($deduction == 2) {$deduction_email = "Cash";}
else if($deduction == 3) {$deduction_email = "Bank Transfer";}
else {$deduction_email = "No deduction";}
$submit_the_bill = "INSERT INTO bill_status
(`bill_status_bill_id`,`bill_status_username`, `bill_status_phone_number`, `bill_status_status`,`bill_paid`, `deduction`)
VALUES ('".$bill_id."', '".$_SESSION['username']."', '".$_SESSION['phone_number']."','1','0','".$deduction."')";
$submit_the_bill_result = $conn->query($submit_the_bill);
$sql_smtp = "SELECT * FROM smtp_settings";
$result_smtp = $conn->query($sql_smtp);
if ($result_smtp->num_rows > 0) {
while($row = $result_smtp->fetch_assoc()) {
$smtp_host = $row['smtp_server'];
$smtp_username = $row['smtp_user_email'];
$smtp_password = $row['smtp_user_password'];
$smtp_ssl = $row['smtp_ssl'];
$smtp_port = $row['smtp_port'];
}
}
if ($smtp_ssl == 1) {$smtp_ssl = "ssl";} else {$smtp_ssl = "tls";}
$mail = new PHPMailer;
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = $smtp_host; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = $smtp_username; // SMTP username
$mail->Password = $smtp_password; // SMTP password
$mail->SMTPSecure = $smtp_ssl; // Enable TLS encryption, `ssl` also accepted
$mail->Port = $smtp_port; // TCP port to connect to
$mail->setFrom('email@example.com', 'Email');
$mail->addAddress($_SESSION['username']); // Name is optional
$mail->isHTML(true); // Set email format to HTML
$mail->Subject = $_SESSION['username']." submitted new bill - ".$_SESSION['bill_period'];
$mail->Body = $_SESSION['username']."(".$_SESSION['phone_number'].") Submit New Bill - ".$_SESSION['bill_period']." <br/><br/>";
$mail->AltBody = $_SESSION['username']."(".$_SESSION['phone_number'].") Submit New Bill - ".$_SESSION['bill_period']." <br/><br/>";
if(!$mail->send()) {
echo 'Message could not be sent.';
echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
//echo 'E-mail sent';
}
unset($_SESSION['bill_period']);
$conn->close();
header("Location:location"); //going to the home page
?>
答案 0 :(得分:1)
对于通过交易解决您的问题,我并不乐观。我认为问题在于代码执行的次数不止一次,如果包装一个事务,您将只对事务运行2个查询,而不是对自动提交运行2个查询。
为什么代码运行两次?您问题中的信息无法回答。我们只能猜测。
很可能是重复的请求,可能是在人工端(由于刷新时间太长或由于重新启动chrome并重新打开标签页或由于某些其他原因而导致刷新),或者是在负载平衡器端(重试失败的请求) )或ajax调用或其他方式。
或者,您的工作流程可能会促使多个人采取相同的行动。例如,如果有多个人拉“最高帐单”,查看它,然后将其标记为完成,则需要在应用程序中执行某些操作,以确保他们不会在大致相同的时间处理所有相同的记录。
值得去研究一下日志和数据行,并验证对插入Web端点的请求数量是否与您的想法相符,并且每个“重复插入”中的数据实际上都是完全相同的。
您的解决方法将取决于原因和您的业务逻辑。您可以使用其他表格为特定用户“签出”账单ID,以确保同一张账单不会被插入两次。您可以给插入请求指定一个ID,以便两次发送相同的插入可以有效地重复数据删除(在电子商务中的每个购物车结帐流程中都实现了最后一个,否则刷新会再次购买您的东西或重新启动不完整的付款流程!)。