最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

數(shù)據(jù)庫面試必備之MySQL中的樂觀鎖與悲觀鎖

 更新時(shí)間:2025年04月18日 10:53:26   作者:大明湖的狗凱.  
這篇文章主要介紹了數(shù)據(jù)庫面試必備之MySQL中樂觀鎖與悲觀鎖的相關(guān)資料,樂觀鎖適用于讀多寫少的場(chǎng)景,通過版本號(hào)檢查避免沖突,而悲觀鎖適用于寫多讀少且對(duì)數(shù)據(jù)一致性要求極高的場(chǎng)景,通過加鎖確保數(shù)據(jù)一致,需要的朋友可以參考下

一、引言

在多用戶并發(fā)訪問數(shù)據(jù)庫的場(chǎng)景中,數(shù)據(jù)的一致性和完整性至關(guān)重要。為了避免并發(fā)操作導(dǎo)致的數(shù)據(jù)沖突問題,MySQL 提供了樂觀鎖和悲觀鎖兩種并發(fā)控制機(jī)制。理解它們的工作原理、適用場(chǎng)景以及如何在實(shí)際代碼中運(yùn)用,對(duì)于開發(fā)高效且可靠的數(shù)據(jù)庫應(yīng)用程序具有關(guān)鍵意義。

二、樂觀鎖

(一)原理

樂觀鎖基于一種樂觀的假設(shè),即認(rèn)為在大多數(shù)情況下,并發(fā)事務(wù)之間不會(huì)發(fā)生沖突。它不會(huì)在事務(wù)開始時(shí)就對(duì)數(shù)據(jù)進(jìn)行加鎖,而是在提交數(shù)據(jù)更新之前,檢查數(shù)據(jù)是否在事務(wù)執(zhí)行期間被其他事務(wù)修改過。如果沒有被修改,則允許提交更新;如果發(fā)現(xiàn)數(shù)據(jù)已經(jīng)被修改,則根據(jù)具體的業(yè)務(wù)邏輯決定是重試更新操作還是拋出異常。

(二)應(yīng)用場(chǎng)景

樂觀鎖適用于讀多寫少的場(chǎng)景,因?yàn)樵谶@種情況下,并發(fā)沖突的概率相對(duì)較低。例如,在一個(gè)電商系統(tǒng)中,商品的瀏覽次數(shù)統(tǒng)計(jì)就是一個(gè)典型的讀多寫少的操作。多個(gè)用戶可以同時(shí)查看商品詳情頁面,而對(duì)瀏覽次數(shù)的更新相對(duì)較少。

(三)示例代碼

假設(shè)我們有一個(gè) products 表,其中包含 id(主鍵)、name、quantity 和 version 字段。version 字段將作為樂觀鎖的版本號(hào)。

-- 創(chuàng)建 products 表
CREATE TABLE products (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50),
  quantity INT,
  version INT
);

以下是在 Java 代碼中使用樂觀鎖更新商品數(shù)量的示例:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class OptimisticLockingExample {
    public static void main(String[] args) {
        // 數(shù)據(jù)庫連接信息
        String url = "jdbc:mysql://localhost:3306/mydb";
        String username = "root";
        String password = "password";

        try (Connection connection = DriverManager.getConnection(url, username, password)) {
            // 開啟事務(wù)
            connection.setAutoCommit(false);

            // 查詢商品信息并獲取當(dāng)前版本號(hào)
            String selectSql = "SELECT quantity, version FROM products WHERE id =?";
            try (PreparedStatement selectStmt = connection.prepareStatement(selectSql)) {
                selectStmt.setInt(1, 1); // 假設(shè)要更新 id 為 1 的商品
                try (ResultSet resultSet = selectStmt.executeQuery()) {
                    if (resultSet.next()) {
                        int currentQuantity = resultSet.getInt("quantity");
                        int currentVersion = resultSet.getInt("version");

                        // 模擬業(yè)務(wù)邏輯,減少商品數(shù)量
                        int newQuantity = currentQuantity - 1;

                        // 更新商品數(shù)量和版本號(hào),使用樂觀鎖機(jī)制
                        String updateSql = "UPDATE products SET quantity =?, version = version + 1 WHERE id =? AND version =?";
                        try (PreparedStatement updateStmt = connection.prepareStatement(updateSql)) {
                            updateStmt.setInt(1, newQuantity);
                            updateStmt.setInt(2, 1); // 商品 id
                            updateStmt.setInt(3, currentVersion);
                            int rowsUpdated = updateStmt.executeUpdate();
                            if (rowsUpdated == 0) {
                                // 說明在更新之前數(shù)據(jù)被其他事務(wù)修改,樂觀鎖沖突
                                System.out.println("樂觀鎖沖突,更新失敗");
                                connection.rollback();
                            } else {
                                // 提交事務(wù)
                                connection.commit();
                                System.out.println("商品數(shù)量更新成功");
                            }
                        }
                    }
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

在上述代碼中,首先查詢商品的當(dāng)前數(shù)量和版本號(hào),然后根據(jù)業(yè)務(wù)需求計(jì)算新的數(shù)量。在更新時(shí),通過 WHERE 子句中的版本號(hào)條件來檢查數(shù)據(jù)是否被其他事務(wù)修改。如果更新的行數(shù)為 0,則表示發(fā)生了樂觀鎖沖突。

三、悲觀鎖

(一)原理

與樂觀鎖相反,悲觀鎖持一種悲觀的態(tài)度,認(rèn)為在并發(fā)環(huán)境中,數(shù)據(jù)很可能會(huì)被其他事務(wù)修改。因此,在事務(wù)開始時(shí),就對(duì)要操作的數(shù)據(jù)進(jìn)行加鎖,直到事務(wù)完成并提交或回滾后才釋放鎖。這樣可以確保在事務(wù)執(zhí)行期間,其他事務(wù)無法對(duì)鎖定的數(shù)據(jù)進(jìn)行修改操作。

(二)應(yīng)用場(chǎng)景

悲觀鎖適用于寫多讀少且對(duì)數(shù)據(jù)一致性要求極高的場(chǎng)景。例如,在銀行系統(tǒng)的轉(zhuǎn)賬操作中,涉及到對(duì)賬戶余額的修改,必須確保在整個(gè)轉(zhuǎn)賬事務(wù)過程中,賬戶余額數(shù)據(jù)不會(huì)被其他并發(fā)事務(wù)干擾,此時(shí)使用悲觀鎖可以有效避免數(shù)據(jù)不一致的問題。

(三)示例代碼

同樣以 products 表為例,在 MySQL 中可以使用 SELECT... FOR UPDATE 語句來實(shí)現(xiàn)悲觀鎖。

-- 開啟事務(wù)
START TRANSACTION;

-- 使用悲觀鎖查詢商品信息并鎖定行
SELECT quantity FROM products WHERE id = 1 FOR UPDATE;

-- 模擬業(yè)務(wù)邏輯,減少商品數(shù)量
UPDATE products SET quantity = quantity - 1 WHERE id = 1;

-- 提交事務(wù)
COMMIT;

在上述 SQL 代碼中,SELECT quantity FROM products WHERE id = 1 FOR UPDATE 語句會(huì)對(duì) id 為 1 的商品行進(jìn)行鎖定,直到事務(wù)提交或回滾。在鎖定期間,其他事務(wù)如果嘗試對(duì)該行數(shù)據(jù)進(jìn)行修改操作,將會(huì)被阻塞,直到鎖被釋放。

四、總結(jié)

樂觀鎖和悲觀鎖是 MySQL 中兩種重要的并發(fā)控制機(jī)制,它們各自適用于不同的應(yīng)用場(chǎng)景。在實(shí)際開發(fā)中,需要根據(jù)業(yè)務(wù)需求、數(shù)據(jù)讀寫比例以及對(duì)數(shù)據(jù)一致性的要求等因素,合理選擇使用樂觀鎖或悲觀鎖,以確保數(shù)據(jù)庫系統(tǒng)在高并發(fā)環(huán)境下能夠穩(wěn)定、高效地運(yùn)行,同時(shí)保證數(shù)據(jù)的完整性和一致性。

到此這篇關(guān)于數(shù)據(jù)庫面試必備之MySQL中的樂觀鎖與悲觀鎖的文章就介紹到這了,更多相關(guān)MySQL樂觀鎖與悲觀鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

河曲县| 平潭县| 枣强县| 游戏| 化德县| 莱西市| 如东县| 平潭县| 武义县| 平陆县| 南木林县| 平谷区| 彭水| 甘南县| 桦川县| 石家庄市| 比如县| 台前县| 都安| 陇西县| 商都县| 福清市| 罗甸县| 南开区| 通州区| 西乌珠穆沁旗| 罗城| 秦皇岛市| 江阴市| 南川市| 金堂县| 崇左市| 平南县| 罗城| 察哈| 中阳县| 疏勒县| 安吉县| 南汇区| 镇巴县| 安乡县|