PHP& MySQL:为什么没有锁就可以工作? [英] PHP & MySQL: Why is this working without lock?

查看:66
本文介绍了PHP& MySQL:为什么没有锁就可以工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用InnoDB并具有下表

I am using InnoDB and have the following table

officeRechNr

year  | month  | id   | 
------------------------
2016  | 7      | 2    | 
2016  | 6      | 5    |
2016  | 5      | 6    |

我的脚本的工作方式如下:

My script works as follows:

  1. officeRechNr 获取当前

id 加1,并在 officeRechNr

回声增加了 id

因此,如果脚本一个接一个地执行,我期望:

So if the script would be executed one after another, I would expect:

New id is 3
New id is 4
New id is 5

我认为当我并行执行脚本时,这种行为会有所不同.

I assumed that this behaves differently when I execute the script parallel.

这是我的剧本:

 $db = new mysqli("localhost","user","pass","db");

 $year     = date("Y");
 $month    = date("m");

 $stmt         = $db->prepare('SELECT zahl FROM officeRechNr WHERE jahr = ? AND monat = ?');

 $stmt->bind_param('ii', $year, $month);
 $stmt->execute();

 $result            =   $stmt->get_result();
 $row           =   $result->fetch_assoc();

 $number       =  $row['zahl'] + 1;
 sleep(20);

 $stmt         = $db->prepare('UPDATE officeRechNr set zahl = ? WHERE jahr = ? and monat = ?');
 $stmt->bind_param('iii',$number, $year, $month);
 $stmt->execute();
 echo "New id is $number";

我同时执行了两个脚本,所以我假设两个脚本的$ number必须等于3,然后它们休眠20秒.因此,我希望

I executed both scripts simultaneously, so I assumed $number must be equal to 3 for both scripts and then they sleep for 20 seconds. Therefore I would expect

New id is 3
New id is 3

令我惊讶的是,结果

New id is 3
New id is 4

我认为我需要对数据库进行写锁定才能实现此结果,如锁定中所述带有php的mysql表.

I thought I need to write-lock the database to achieve this result, as explained in Lock mysql table with php.

为什么我没有得到预期的结果?该脚本是否总是返回不同的ID-即使在完全相同的时间执行?

Why did I not get the expected outcome? Does this script always return different id's - even if executed at exact same time?

推荐答案

如果要锁定而不是全表锁定,请尝试在事务中使用SELECT...FOR UPDATE来仅锁定所选行(假设您具有索引)贾尔(monat).参见 http://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html

If you want locking but not full-table locking, try using SELECT...FOR UPDATE in a transaction to lock just the rows you select (assuming you have an index on jahr, monat). See http://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html

或者,您根本不需要锁定.您可以使用

Alternatively, you don't need locking at all. You could use

UPDATE officeRechNr set zahl = LAST_INSERT_ID(zahl+1) WHERE jahr = ? and monat = ?

阅读 http:的文档://dev.mysql.com/doc/refman/5.7/zh-CN/information-functions.html#function_last-insert-id 了解详情.

这篇关于PHP& MySQL:为什么没有锁就可以工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆