123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>1. 事务处理</title>
- <style>
- /* From extension vscode.github */
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- .vscode-dark img[src$=\#gh-light-mode-only],
- .vscode-light img[src$=\#gh-dark-mode-only],
- .vscode-high-contrast:not(.vscode-high-contrast-light) img[src$=\#gh-light-mode-only],
- .vscode-high-contrast-light img[src$=\#gh-dark-mode-only] {
- display: none;
- }
- </style>
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex/dist/katex.min.css">
- <link href="https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.css" rel="stylesheet" type="text/css">
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/markdown.css">
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/highlight.css">
- <style>
- body {
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe WPC', 'Segoe UI', system-ui, 'Ubuntu', 'Droid Sans', sans-serif;
- font-size: 14px;
- line-height: 1.6;
- }
- </style>
- <style>
- .task-list-item {
- list-style-type: none;
- }
- .task-list-item-checkbox {
- margin-left: -20px;
- vertical-align: middle;
- pointer-events: none;
- }
- </style>
- <style>
- :root {
- --color-note: #0969da;
- --color-tip: #1a7f37;
- --color-warning: #9a6700;
- --color-severe: #bc4c00;
- --color-caution: #d1242f;
- --color-important: #8250df;
- }
- </style>
- <style>
- @media (prefers-color-scheme: dark) {
- :root {
- --color-note: #2f81f7;
- --color-tip: #3fb950;
- --color-warning: #d29922;
- --color-severe: #db6d28;
- --color-caution: #f85149;
- --color-important: #a371f7;
- }
- }
- </style>
- <style>
- .markdown-alert {
- padding: 0.5rem 1rem;
- margin-bottom: 16px;
- color: inherit;
- border-left: .25em solid #888;
- }
- .markdown-alert>:first-child {
- margin-top: 0
- }
- .markdown-alert>:last-child {
- margin-bottom: 0
- }
- .markdown-alert .markdown-alert-title {
- display: flex;
- font-weight: 500;
- align-items: center;
- line-height: 1
- }
- .markdown-alert .markdown-alert-title .octicon {
- margin-right: 0.5rem;
- display: inline-block;
- overflow: visible !important;
- vertical-align: text-bottom;
- fill: currentColor;
- }
- .markdown-alert.markdown-alert-note {
- border-left-color: var(--color-note);
- }
- .markdown-alert.markdown-alert-note .markdown-alert-title {
- color: var(--color-note);
- }
- .markdown-alert.markdown-alert-important {
- border-left-color: var(--color-important);
- }
- .markdown-alert.markdown-alert-important .markdown-alert-title {
- color: var(--color-important);
- }
- .markdown-alert.markdown-alert-warning {
- border-left-color: var(--color-warning);
- }
- .markdown-alert.markdown-alert-warning .markdown-alert-title {
- color: var(--color-warning);
- }
- .markdown-alert.markdown-alert-tip {
- border-left-color: var(--color-tip);
- }
- .markdown-alert.markdown-alert-tip .markdown-alert-title {
- color: var(--color-tip);
- }
- .markdown-alert.markdown-alert-caution {
- border-left-color: var(--color-caution);
- }
- .markdown-alert.markdown-alert-caution .markdown-alert-title {
- color: var(--color-caution);
- }
- </style>
-
- </head>
- <body class="vscode-body vscode-light">
- <blockquote>
- <p>以下工具类库,默认基于laravel框架</p>
- </blockquote>
- <blockquote>
- <p>开始开发前,每个项目参与者都必须对laravel、dcat中的一些模块或概念有个基本的认识。否则将无法有效提供AI提示词,则无法加快研发效率。 要求每个人在业余时间对官方文档提供的每一个功能点,做一个开发和测试,这样建立基本的认识。</p>
- </blockquote>
- <h4 id="1-事务处理">1. 事务处理</h4>
- <h5 id="场景说明">场景说明</h5>
- <ul>
- <li>
- <p><strong>串行化 (SERIALIZABLE)</strong>:适用于需要严格事务隔离的场景,例如银行转账,确保事务完全隔离,避免所有并发问题,但可能会影响性能。</p>
- </li>
- <li>
- <p><strong>可重复读 (REPEATABLE READ)</strong>:适用于需要保证在同一事务中多次读取同一数据的一致性的场景,例如库存查询和减少操作,避免在事务过程中数据被其他事务修改。</p>
- </li>
- <li>
- <p><strong>读已提交 (READ COMMITTED)</strong>:适用于大多数需要避免脏读的场景,每次读取都能看到其他事务的最新提交结果,但可能会出现不可重复读和幻读。</p>
- </li>
- <li>
- <p><strong>读未提交 (READ UNCOMMITTED)</strong>:适用于读操作对数据一致性要求不高的场景,允许读取到其他事务未提交的数据,可能会导致脏读、不可重复读和幻读。</p>
- </li>
- </ul>
- <h5 id="用法举例">用法举例</h5>
- <pre><code class="language-php"><span class="hljs-comment">// 串行化 (SERIALIZABLE) - 最严格的隔离级别,完全隔离,事务串行执行</span>
- <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">DB</span>;
- DB::<span class="hljs-title function_ invoke__">transaction</span>(function () {
- <span class="hljs-comment">// 操作1:读取用户A的当前余额</span>
- <span class="hljs-variable">$balanceA</span> = DB::<span class="hljs-title function_ invoke__">table</span>(<span class="hljs-string">'accounts'</span>)-><span class="hljs-title function_ invoke__">where</span>(<span class="hljs-string">'user_id'</span>, <span class="hljs-variable">$userIdA</span>)-><span class="hljs-title function_ invoke__">value</span>(<span class="hljs-string">'balance'</span>);
- <span class="hljs-comment">// 操作2:减少用户A的余额</span>
- DB::<span class="hljs-title function_ invoke__">table</span>(<span class="hljs-string">'accounts'</span>)-><span class="hljs-title function_ invoke__">where</span>(<span class="hljs-string">'user_id'</span>, <span class="hljs-variable">$userIdA</span>)-><span class="hljs-title function_ invoke__">decrement</span>(<span class="hljs-string">'balance'</span>, <span class="hljs-variable">$amount</span>);
- <span class="hljs-comment">// 操作3:增加用户B的余额</span>
- DB::<span class="hljs-title function_ invoke__">table</span>(<span class="hljs-string">'accounts'</span>)-><span class="hljs-title function_ invoke__">where</span>(<span class="hljs-string">'user_id'</span>, <span class="hljs-variable">$userIdB</span>)-><span class="hljs-title function_ invoke__">increment</span>(<span class="hljs-string">'balance'</span>, <span class="hljs-variable">$amount</span>);
- }, DB::<span class="hljs-variable constant_">TRANSACTION_SERIALIZABLE</span>);
- </code></pre>
- <pre><code class="language-php"><span class="hljs-comment">// 可重复读 (REPEATABLE READ) - 保证事务中每次读取结果都相同,避免不可重复读和脏读</span>
- <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">DB</span>;
- DB::<span class="hljs-title function_ invoke__">transaction</span>(function () {
-
- }, DB::<span class="hljs-variable constant_">TRANSACTION_REPEATABLE_READ</span>);
- </code></pre>
- <pre><code class="language-php"><span class="hljs-comment">// 读已提交 (READ COMMITTED) - 每次读取只能看到其他事务已经提交的数据,避免脏读</span>
- <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">DB</span>;
- DB::<span class="hljs-title function_ invoke__">transaction</span>(function () {
-
- }, DB::<span class="hljs-variable constant_">TRANSACTION_READ_COMMITTED</span>);
- </code></pre>
- <pre><code class="language-php"><span class="hljs-comment">// 读未提交 (READ UNCOMMITTED) - 最宽松的隔离级别,可能会读取到其他事务未提交的数据(脏读)</span>
- <span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">DB</span>;
- DB::<span class="hljs-title function_ invoke__">transaction</span>(function () {
-
- }, DB::<span class="hljs-variable constant_">TRANSACTION_READ_UNCOMMITTED</span>);
- </code></pre>
- <h5 id="事务嵌套">事务嵌套</h5>
- <p>在 Laravel 中,如果你在一个 DB::transaction 回调中调用另一个也使用 DB::transaction 的方法,将会出现以下情况:</p>
- <pre><code>嵌套事务:Laravel 支持嵌套事务。当你在事务中调用另一个事务时,Laravel 会使用保存点(Savepoints)来处理嵌套的事务。保存点允许你在事务中设置一个点,之后可以回滚到这个点,而不影响事务中之前的操作。
- 保存点的创建:对于每个嵌套的事务,Laravel 会创建一个保存点。如果内部事务成功提交,保存点会被释放;如果内部事务失败并回滚,只有内部事务的更改会被回滚到保存点,外部事务的其他操作不受影响。
- 事务的回滚:如果内部事务中抛出异常,整个内部事务会被回滚到最近的保存点。如果外部事务中抛出异常,整个外部事务(包括所有内部事务)会被回滚。
- </code></pre>
- <p>下面是一个示例,说明这种情况:</p>
- <pre><code class="language-php"><span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">DB</span>;
- DB::<span class="hljs-title function_ invoke__">transaction</span>(function () {
- <span class="hljs-comment">// 外部事务开始</span>
- <span class="hljs-comment">// 一些数据库操作</span>
- DB::<span class="hljs-title function_ invoke__">table</span>(<span class="hljs-string">'accounts'</span>)-><span class="hljs-title function_ invoke__">insert</span>([...]);
- <span class="hljs-variable language_">$this</span>-><span class="hljs-title function_ invoke__">nestedTransaction</span>(); <span class="hljs-comment">// 调用包含内部事务的方法</span>
- <span class="hljs-comment">// 更多数据库操作</span>
- DB::<span class="hljs-title function_ invoke__">table</span>(<span class="hljs-string">'accounts'</span>)-><span class="hljs-title function_ invoke__">update</span>([...]);
- }, DB::<span class="hljs-variable constant_">TRANSACTION_SERIALIZABLE</span>);
- <span class="hljs-comment">// 包含内部事务的方法</span>
- <span class="hljs-keyword">protected</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">nestedTransaction</span>(<span class="hljs-params"></span>)
- </span>{
- DB::<span class="hljs-title function_ invoke__">transaction</span>(function () {
- <span class="hljs-comment">// 内部事务开始</span>
- <span class="hljs-comment">// 一些数据库操作</span>
- DB::<span class="hljs-title function_ invoke__">table</span>(<span class="hljs-string">'accounts'</span>)-><span class="hljs-title function_ invoke__">insert</span>([...]);
- <span class="hljs-comment">// 假设这里发生了错误,内部事务会回滚</span>
- <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Exception</span>(<span class="hljs-string">'Something went wrong!'</span>);
- <span class="hljs-comment">// 更多数据库操作,如果内部事务成功,这些操作会执行</span>
- DB::<span class="hljs-title function_ invoke__">table</span>(<span class="hljs-string">'accounts'</span>)-><span class="hljs-title function_ invoke__">update</span>([...]);
- }, DB::<span class="hljs-variable constant_">TRANSACTION_SERIALIZABLE</span>);
- }
- </code></pre>
- <blockquote>
- <p>在这个例子中,如果 nestedTransaction 方法中的内部事务因为抛出异常而失败,只有内部事务中的操作会被回滚。外部事务中的操作(在调用 nestedTransaction 之前和之后的操作)不会受到影响,除非外部事务本身抛出异常。</p>
- </blockquote>
- <h4 id="2-队列处理">2. 队列处理</h4>
- <p><a href="https://learnku.com/docs/laravel/9.x/queues/12236#0796f7">参考laravel官方文档</a></p>
- <h4 id="3-缓存处理">3. 缓存处理</h4>
- <p><a href="https://learnku.com/docs/laravel/9.x/redis/12250#e11144">参考laravel官方文档</a></p>
- <h4 id="4-日志记录">4. 日志记录</h4>
- <p><a href="https://learnku.com/docs/laravel/9.x/logging/12237#0796f7">参考laravel官方文档</a></p>
- <h4 id="5-其他请参考官方文档">5. 其他请参考官方文档</h4>
- <p><a href="https://learnku.com/docs/laravel/9.x">laravel官方文档</a></p>
- <p><a href="https://learnku.com/docs/dcat-admin/2.x">dcat文档</a></p>
- <script async src="https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.js"></script>
-
- </body>
- </html>
|