国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

PHP 和 MySQL 如何處理并發(fā)請(qǐng)求?
P粉037215587
P粉037215587 2023-09-05 12:17:19
[PHP討論組]
<p>我一定遺漏了一些關(guān)于 PHP/Symfony 如何處理并發(fā)請(qǐng)求的信息,或者可能如何處理數(shù)據(jù)庫(kù)上的潛在并發(fā)查詢......</p> <p>這段代碼似乎在做不可能的事情 - 它隨機(jī)(大約每月一次)在底部創(chuàng)建新實(shí)體的副本。我的結(jié)論是,當(dāng)兩個(gè)客戶端兩次發(fā)出相同的請(qǐng)求,并且兩個(gè)線程同時(shí)執(zhí)行 SELECT 查詢,選取 stop == NULL 的條目,然后它們都(?)設(shè)置該條目的停止時(shí)間時(shí),一定會(huì)發(fā)生這種情況,他們都寫了一個(gè)新條目。</p> <p>據(jù)我所知,這是我的邏輯大綱:</p> <ol> <li>獲取所有停止時(shí)間為 NULL 的條目</li> <li>循環(huán)這些條目</li> <li>僅當(dāng)輸入日期 (UTC) 與當(dāng)前日期 (UTC) 不同時(shí)才繼續(xù)</li> <li>將打開條目的停止時(shí)間設(shè)置為 23:59:59 并刷新到數(shù)據(jù)庫(kù)</li> <li>構(gòu)建一個(gè)新條目,開始時(shí)間為第二天的 00:00:00</li> <li>斷言該位置沒有其他未結(jié)條目</li> <li>斷言該位置沒有未來的條目</li> <li>只有這樣 - 將新條目刷新到數(shù)據(jù)庫(kù)</li> </ol> <p>控制器自動(dòng)關(guān)閉和打開</p> <pre class="brush:php;toolbar:false;">//if entry spans daybreak (midnight) close it and open a new entry at the beginning of next day private function autocloseAndOpen($units) { $now = new \DateTime(&quot;now&quot;, new \DateTimeZone(&quot;UTC&quot;)); $repository = $this-&gt;em-&gt;getRepository('App\Entity\Poslog\Entry'); $query = $repository-&gt;createQueryBuilder('e') -&gt;where('e.stop is NULL') -&gt;getQuery(); $results = $query-&gt;getResult(); if (!isset($results[0])) { return null; //there are no open entries at all } $em = $this-&gt;em; $messages = &quot;&quot;; foreach ($results as $r) { if ($r-&gt;getPosition()-&gt;getACRGroup() == $unit) { //only touch the user's own entries $start = $r-&gt;getStart(); //Assert entry spanning datebreak $startStr = $start-&gt;format(&quot;Y-m-d&quot;); //Necessary for comparison, if $start-&gt;format(&quot;Y-m-d&quot;) is put in the comparison clause PHP will still compare the datetime object being formatted, not the output of the formatting. $nowStr = $now-&gt;format(&quot;Y-m-d&quot;); //Necessary for comparison, if $start-&gt;format(&quot;Y-m-d&quot;) is put in the comparison clause PHP will still compare the datetime object being formatted, not the output of the formatting. if ($startStr &lt; $nowStr) { $stop = new \DateTimeImmutable($start-&gt;format(&quot;Y-m-d&quot;).&quot;23:59:59&quot;, new \DateTimeZone(&quot;UTC&quot;)); $r-&gt;setStop($stop); $em-&gt;flush(); $txt = $unit-&gt;getName() . &quot; had an entry in position (&quot; . $r-&gt;getPosition()-&gt;getName() . &quot;) spanning datebreak (UTC). Automatically closed at &quot; . $stop-&gt;format(&quot;Y-m-d H:i:s&quot;) . &quot;z.&quot;; $messages .= &quot;&lt;p&gt;&quot; . $txt . &quot;&lt;/p&gt;&quot;; //Open new entry $newStartTime = $stop-&gt;modify('+1 second'); $entry = new Entry(); $entry-&gt;setStart( $newStartTime ); $entry-&gt;setOperator( $r-&gt;getOperator() ); $entry-&gt;setPosition( $r-&gt;getPosition() ); $entry-&gt;setStudent( $r-&gt;getStudent() ); $em-&gt;persist($entry); //Assert that there are no future entries before autoopening a new entry $futureE = $this-&gt;checkFutureEntries($r-&gt;getPosition(),true); $openE = $this-&gt;checkOpenEntries($r-&gt;getPosition(), true); if ($futureE !== 0 || $openE !== 0) { $txt = &quot;Tried to open a new entry for &quot; . $r-&gt;getOperator()-&gt;getSignature() . &quot; in the same position (&quot; . $r-&gt;getPosition()-&gt;getName() . &quot;) next day but there are conflicting entries.&quot;; $messages .= &quot;&lt;p&gt;&quot; . $txt . &quot;&lt;/p&gt;&quot;; } else { $em-&gt;flush(); //store to DB $txt = &quot;A new entry was opened for &quot; . $r-&gt;getOperator()-&gt;getSignature() . &quot; in the same position (&quot; . $r-&gt;getPosition()-&gt;getName() . &quot;)&quot;; $messages .= &quot;&lt;p&gt;&quot; . $txt . &quot;&lt;/p&gt;&quot;; } } } } return $messages; }</pre> <p>我什至在這里使用 checkOpenEntries() 運(yùn)行額外的檢查,以查看此時(shí)該位置是否存在任何 stoptime == NULL 的條目。最初,我認(rèn)為這是多余的,因?yàn)槲艺J(rèn)為如果一個(gè)請(qǐng)求正在數(shù)據(jù)庫(kù)上運(yùn)行和操作,則另一個(gè)請(qǐng)求只有在第一個(gè)請(qǐng)求完成后才會(huì)啟動(dòng)。</p> <pre class="brush:php;toolbar:false;">private function checkOpenEntries($position,$checkRelatives = false) { $positionsToCheck = array(); if ($checkRelatives == true) { $positionsToCheck = $position-&gt;getRelatedPositions(); $positionsToCheck[] = $position; } else { $positionsToCheck = array($position); } //Get all open entries for position $repository = $this-&gt;em-&gt;getRepository('App\Entity\Poslog\Entry'); $query = $repository-&gt;createQueryBuilder('e') -&gt;where('e.stop is NULL and e.position IN (:positions)') -&gt;setParameter('positions', $positionsToCheck) -&gt;getQuery(); $results = $query-&gt;getResult(); if(!isset($results[0])) { return 0; //tells caller that there are no open entries } else { if (count($results) === 1) { return $results[0]; //if exactly one open entry, return that object to caller } else { $body = 'Found more than 1 open log entry for position ' . $position-&gt;getName() . ' in ' . $position-&gt;getACRGroup()-&gt;getName() . ' this should not be possible, there appears to be corrupt data in the database.'; $this-&gt;email($body); $output['success'] = false; $output['message'] = $body . ' An automatic email has been sent to ' . $this-&gt;globalParameters-&gt;get('poslog-email-to') . ' to notify of the problem, manual inspection is required.'; $output['logdata'] = null; return $this-&gt;prepareResponse($output); } } }</pre> <p>我是否需要使用某種“鎖定數(shù)據(jù)庫(kù)”方法來啟動(dòng)此功能才能實(shí)現(xiàn)我想要做的事情?</p> <p>我已經(jīng)測(cè)試了所有功能,并且當(dāng)我模擬各種狀態(tài)時(shí)(即使不應(yīng)該如此,也為停止時(shí)間輸入 NULL 等),一切都正常。大多數(shù)情況下,一切都運(yùn)行良好,但在月中的某一天,這種事情發(fā)生了......</p>
P粉037215587
P粉037215587

全部回復(fù)(1)
P粉921165181

您永遠(yuǎn)無法保證順序(或隱式獨(dú)占訪問)。嘗試一下,你就會(huì)把自己挖掘得越來越深。

正如 Matt 和 KIKO 在評(píng)論中提到的,您可以使用約束和事務(wù),這些應(yīng)該會(huì)有很大幫助,因?yàn)槟臄?shù)據(jù)庫(kù)將保持干凈,但請(qǐng)記住您的應(yīng)用程序需要能夠捕獲數(shù)據(jù)庫(kù)層產(chǎn)生的錯(cuò)誤。 絕對(duì)值得首先嘗試。

處理此問題的另一種方法是強(qiáng)制數(shù)據(jù)庫(kù)/應(yīng)用程序級(jí)別鎖定。

數(shù)據(jù)庫(kù)級(jí)鎖定更加粗糙,如果您在某個(gè)地方忘記釋放鎖定(在長(zhǎng)時(shí)間運(yùn)行的腳本中),則非常不可原諒。

MySQL 文檔:

鎖定整個(gè)表通常是一個(gè)壞主意,但它是可行的。這很大程度上取決于應(yīng)用程序。

一些開箱即用的 ORM 支持對(duì)象版本控制,如果版本在執(zhí)行過程中發(fā)生更改,則會(huì)拋出異常。理論上,您的應(yīng)用程序會(huì)遇到異常,重試時(shí)會(huì)發(fā)現(xiàn)其他人已經(jīng)填充了該字段,并且不再是更新的候選者。

應(yīng)用程序級(jí)鎖定更加細(xì)粒度,但代碼中的所有點(diǎn)都需要遵守鎖定,否則,您將回到方#1。如果您的應(yīng)用程序是分布式的(比如 K8S,或者只是部署在多個(gè)服務(wù)器上),那么您的鎖定機(jī)制也必須是分布式的(不是實(shí)例本地的)

最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板
關(guān)于我們 免責(zé)申明 意見反饋 講師合作 廣告合作 最新更新
php中文網(wǎng):公益在線php培訓(xùn),幫助PHP學(xué)習(xí)者快速成長(zhǎng)!
關(guān)注服務(wù)號(hào) 技術(shù)交流群
PHP中文網(wǎng)訂閱號(hào)
每天精選資源文章推送
PHP中文網(wǎng)APP
隨時(shí)隨地碎片化學(xué)習(xí)
PHP中文網(wǎng)抖音號(hào)
發(fā)現(xiàn)有趣的

Copyright 2014-2025 http://m.miracleart.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號(hào)