生成式AI情绪安全检测框架与工程实践
2026/7/26 15:58:43
乐观锁(Optimistic Locking)是一种并发控制机制,其核心思想是"假设冲突很少发生"。与悲观锁(Pessimistic Locking)不同,悲观锁在访问共享资源前会先加锁,阻止其他线程同时访问;而乐观锁则假设数据在大多数情况下不会发生冲突,因此在读取数据时不加锁,仅在更新数据时检查数据是否被其他线程修改过。
乐观锁通常通过版本号(Version Number)或时间戳(Timestamp)来实现:
sql -- 读取数据 SELECT id, name, version FROM table WHERE id = 1; -- 更新数据(带版本号验证) UPDATE table SET name = 'new_value', version = version + 1 WHERE id = 1 AND version = current_version;如果UPDATE语句影响的行数为0,说明数据在读取后被其他线程修改过,需要重新获取数据并重试操作。
乐观锁广泛应用于以下场景:
让我通过一个完整的示例来说明乐观锁是如何在实际场景中被触发的。
假设我们有一个酒店预订系统,两个前台工作人员Alice和Bob同时处理同一个预订记录:
Alice打开预订记录,准备更新联系人信息:
javascript // Alice读取预订信息 const reservation = await getRoomReservationById(1001); // 返回数据: // { // id: 1001, // contactName: "张三", // phoneNumber: "13800138000", // version: 1, // status: "待确认" // }几乎同时,Bob也打开了同一份预订记录:
javascript // Bob读取预订信息 const reservation = await getRoomReservationById(1001); // 返回相同的数据: // { // id: 1001, // contactName: "张三", // phoneNumber: "13800138000", // version: 1, // status: "待确认" // }Alice首先完成修改并提交:
javascript // Alice尝试更新预订信息 const updateData = { id: 1001, contactName: "张三丰", // 修改联系人姓名 phoneNumber: "13800138000", version: 1, // Alice读取时的版本号 status: "待确认" }; // 发送到后端的更新请求 await updateRoomReservation(updateData);后端执行SQL:
sql UPDATE room_reservation SET contact_name = '张三丰', version = version + 1 WHERE id = 1001 AND version = 1;结果: 影响1行记录,更新成功,数据库中版本号变为2。
Bob稍后提交他的修改(更新电话号码):
javascript // Bob尝试更新预订信息 const updateData = { id: 1001, contactName: "张三", // Bob未修改联系人姓名 phoneNumber: "13900139000", // 修改电话号码 version: 1, // Bob读取时的版本号(仍然是1) status: "待确认" }; // 发送到后端的更新请求 await updateRoomReservation(updateData);后端执行SQL:
sql UPDATE room_reservation SET phone_number = '13900139000', version = version + 1 WHERE id = 1001 AND version = 1; -- 注意:这里的version是1关键点: 此时数据库中预订ID为1001的记录的版本号已经是2(被Alice的更新操作递增了),但Bob的更新请求仍然使用版本号1作为条件。
执行结果:
javascript try { await updateRoomReservation(updateData); console.log("更新成功"); } catch (error) { if (error.message.includes("乐观锁")) { // 乐观锁冲突处理 alert("检测到数据冲突,请刷新后重试"); // 重新加载最新数据 const latestReservation = await getRoomReservationById(1001); // 提示用户数据已被其他用户修改 console.log("最新数据:", latestReservation); } }javascript // 带重试机制的更新函数 async function updateReservationWithRetry(reservationData, maxRetries = 3) { let retries = 0; while (retries < maxRetries) { try { // 尝试更新 await updateRoomReservation(reservationData); console.log("更新成功"); return true; } catch (error) { if (error.message.includes("乐观锁") || error.response?.data?.code === 500) { retries++; if (retries >= maxRetries) { alert("更新失败次数过多,请稍后重试"); return false; } console.log(`乐观锁冲突,第${retries}次重试`); // 重新获取最新数据 const latestData = await getRoomReservationById(reservationData.id); // 合并用户的新修改到最新数据中 reservationData.version = latestData.data.version; // 使用最新版本号 // 这里可能需要合并用户的修改到最新数据中 // 具体实现取决于业务逻辑 console.log(`重试第${retries}次,使用版本号: ${reservationData.version}`); } else { // 非乐观锁错误,直接抛出 throw error; } } } }乐观锁的触发是并发控制的正常表现:
这种机制确保了在高并发场景下数据的完整性,同时避免了传统锁机制可能带来的性能问题。