<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 不支持事務 我們繼續上一章節的內容,大家應該記得我們`Lua`代碼中是如何完成`ngx_postgres`模塊調用的。我們把他簡單改造一下,讓他更接近真實代碼。 ~~~ local json = require "cjson" function db_exec(sql_str) local res = ngx.location.capture('/postgres', { args = {sql = sql_str } } ) local status = res.status local body = json.decode(res.body) if status == 200 then status = true else status = false end return status, body end -- 轉賬操作,對ID=100的用戶加10,同時對ID=200的用戶減10。 ? local status ? status = db_exec("BEGIN") ? if status then ? db_exec("ROLLBACK") ? end ? ? status = db_exec("UPDATE ACCOUNT SET MONEY=MONEY+10 WHERE ID = 100") ? if status then ? db_exec("ROLLBACK") ? end ? ? status = db_exec("UPDATE ACCOUNT SET MONEY=MONEY-10 WHERE ID = 200") ? if status then ? db_exec("ROLLBACK") ? end ? ? db_exec("COMMIT") ~~~ 后面這部分有問題的代碼,在沒有并發的場景下使用,是不會有任何問題的。但是這段代碼在高并發應用場景下,錯誤百出。你會發現最后執行結果完全摸不清楚。明明是個轉賬邏輯,一個收入,一直支出,最后卻發現總收入比支出要大。如果這個錯誤發生在金融領域,那不知道要賠多少錢。 如果你能靠自己很快明白錯誤的原因,那么恭喜你你對數據庫連接、`Nginx`機理都是比較清楚的。如果你想不明白,那就聽我給你掰一掰這面的小知識。 數據庫的事物成功執行,事物相關的所有操作是必須執行在一條連接上的。`SQL`的執行情況類似這樣: ~~~ 連接:`BEGIN` -> `SQL(UPDATE、DELETE... ...)` -> `COMMIT`。 ~~~ 但如果你創建了兩條連接,每條連接提交的SQL語句是下面這樣: ~~~ 連接1:`BEGIN` -> `SQL(UPDATE、DELETE... ...)` 連接2:`COMMIT` ~~~ 這時就會出現連接1的內容沒有被提交,行鎖產生。連接2提交了一個空的`COMMIT`。 說到這里你可能開始鄙視我了,誰瘋了非要創建兩條連接來這么用SQL啊。有麻煩,又不好看,貌似從來沒聽說過還有人在一次請求中創建多個數據庫連接,簡直就是非人類嘛。 或許你不會主動、顯示的創建多個連接,但是剛剛的示例代碼,高并發下這個事物的每個SQL語句都可能落在不同的連接上。為什么呢?這是因為通過`ngx.location.capture`跳轉到`/postgres`小節后,`Nginx`每次都會從連接池中挑選一條空閑連接,二當時那條連接是空閑的,完全沒法預估。所以上面的第二個例子,就這么靜悄悄的發生了。如果你不了解`Nginx`的機理,那么他肯定會一直困擾你。為什么一會兒好,一會兒不好。 同樣的道理,我們推理到`DrizzleNginxModule`、`RedisNginxModule`、`Redis2NginxModule`,他們都是無法做到在兩次連續請求落到同一個連接上的。 由于這個`Bug`藏得比較深,并且不太好講解,所以我覺得生產中最好用`lua-resty-*`這類的庫,更符合標準調用習慣,直接可以繞過這些坑。不要為了一點點的性能,犧牲了更大的蛋糕。看得見的,看不見的,都要了解用用,最后再做決定,肯定不吃虧。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看