PHP使用数据库的并发问题

发表于:2015-8-21 10:29

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:林中侠客    来源:51Testing软件测试网采编

分享:
  在并行系统中并发问题永远不可忽视。尽管PHP语言原生没有提供多线程机制,那并不意味着所有的操作都是线程安全的。尤其是在操作诸如订单、支付等业务系统中,更需要注意操作数据库的并发问题。
  接下来我通过一个案例分析一下PHP操作数据库时并发问题的处理问题。
  首先,我们有这样一张数据表:
  1 mysql> select * from counter;
  2 +----+-----+
  3 | id | num |
  4 +----+-----+
  5 |  1 |   0 |
  6 +----+-----+
  7 1 row in set (0.00 sec)
  这段代码模拟了一次业务操作:
1 <?php
2 function dummy_business() {
3     $conn = mysqli_connect('127.0.0.1', 'public', 'public') or die(mysqli_error());
4     mysqli_select_db($conn, 'test');
5     for ($i = 0; $i < 10000; $i++) {
6         mysqli_query($conn, 'UPDATE counter SET num = num + 1 WHERE id = 1');
7     }
8     mysqli_close($conn);
9 }
10
11 for ($i = 0; $i < 10; $i++) {
12     $pid = pcntl_fork();
13
14     if($pid == -1) {
15         die('can not fork.');
16     } elseif (!$pid) {
17         dummy_business();
18         echo 'quit'.$i.PHP_EOL;
19         break;
20     }
21 }
22 ?>
  上面的代码模拟了10个用户同时并发执行一项业务的情况,每次业务操作都会使得num的值增加1,每个用户都会执行10000次操作,最终num的值应当是100000。
  运行这段代码,num的值和我们预期的值是一样的:
  1 mysql> select * from counter;
  2 +----+--------+
  3 | id | num    |
  4 +----+--------+
  5 |  1 | 100000 |
  6 +----+--------+
  7 1 row in set (0.00 sec)
  这里不会出现问题,是因为单条UPDATE语句操作是原子的,无论怎么执行,num的值最终都会是100000。
  然而很多情况下,我们业务过程中执行的逻辑,通常是先查询再执行,并不像上面的自增那样简单:
1 <?php
2 function dummy_business() {
3     $conn = mysqli_connect('127.0.0.1', 'public', 'public') or die(mysqli_error());
4     mysqli_select_db($conn, 'test');
5     for ($i = 0; $i < 10000; $i++) {
6         $rs = mysqli_query($conn, 'SELECT num FROM counter WHERE id = 1');
7         mysqli_free_result($rs);
8         $row = mysqli_fetch_array($rs);
9         $num = $row[0];
10         mysqli_query($conn, 'UPDATE counter SET num = '.$num.' + 1 WHERE id = 1');
11     }
12     mysqli_close($conn);
13 }
14
15 for ($i = 0; $i < 10; $i++) {
16     $pid = pcntl_fork();
17
18     if($pid == -1) {
19         die('can not fork.');
20     } elseif (!$pid) {
21         dummy_business();
22         echo 'quit'.$i.PHP_EOL;
23         break;
24     }
25 }
26 ?>
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号