我们的文章会在微信公众号IT民工的龙马人生和博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢!
由于博客中有大量代码,通过页面浏览效果更佳。
本文为个人学习《Expert Oracle Database Architecture Techniques and Solutions for High Performance and Productivity(第四版本》一书过程中的笔记与理解分享,仅用于学习与交流,部分内容参考原书观点并结合>实际经验进行整理。若涉及版权问题,请联系删除或沟通处理。也请大家支持购买原版书籍。
数据库锁定机制:如何避免数据冲突
在开发多用户数据库应用时,最大的挑战之一就是如何在保证数据一致性的同时,让多个用户能够同时访问和修改数据。今天我们就来聊聊Oracle数据库中的锁定机制,以及如何避免常见的"丢失更新"问题。
什么是数据库锁?
想象一下图书馆里借书的情景:当一本书被借出时,其他读者就不能再借这本书了。数据库锁也是类似的机制,它用来管理对共享资源的访问。在数据库中,锁不仅用于锁定表中的行,还用于控制对存储过程等各种资源的并发访问。
为什么不同数据库的锁机制不同?
就像不同品牌的手机操作系统不同一样,Oracle、SQL Server、MySQL等数据库的锁实现方式也各不相同。我曾经使用过多种数据库,发现它们处理锁的方式差异很大:
- 早期SQL Server使用页级锁(锁定整页数据),导致并发性能很差
- Informix虽然支持行级锁,但开销很大,锁数量有限制
- Oracle的行级锁则非常高效,无论锁定1行还是100万行,资源消耗几乎相同
常见问题:丢失更新
最典型的并发问题是"丢失更新"。举个员工信息更新的例子:
- 用户A查询员工信息(地址:旧地址)
- 用户B也查询同一员工信息
- 用户A修改地址为新地址并保存
- 用户B修改电话号码并保存
结果:用户B的更新会覆盖用户A的地址修改,导致地址又变回旧地址!
解决方案一:悲观锁
悲观锁就像"先占位再修改"的策略。具体做法是:
- 查询数据时立即锁定:
SELECT ... FOR UPDATE NOWAIT
- 如果锁定成功,确保数据未被修改
- 执行更新并提交
-- 先锁定要修改的行
SELECT empno, ename, sal FROM emp
WHERE empno = :empno
FOR UPDATE NOWAIT;-- 确认锁定后执行更新
UPDATE emp SET ename = :ename, sal = :sal
WHERE empno = :empno;
COMMIT;
优点:绝对安全,不会出现并发冲突
缺点:需要保持数据库连接,不适合Web应用
解决方案二:乐观锁
乐观锁就像"先修改再检查"的策略。常用实现方式有:
1. 版本号列法
给表添加一个版本号或时间戳列:
CREATE TABLE dept (deptno NUMBER(2),dname VARCHAR2(14),loc VARCHAR2(13),last_mod TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL
);
更新时检查版本号:
UPDATE dept
SET dname = :dname, last_mod = SYSTIMESTAMP
WHERE deptno = :deptno
AND last_mod = :original_last_mod;
如果返回0行更新,说明数据已被他人修改。
2. 校验和法
使用ORA_HASH等函数计算数据指纹:
-- 查询时计算哈希值
SELECT deptno, dname, loc, ORA_HASH(dname || '/' || loc) hash
FROM dept WHERE deptno = 10;-- 更新时验证哈希
UPDATE dept SET dname = :dname
WHERE deptno = :deptno
AND ORA_HASH(dname || '/' || loc) = :original_hash;
如何选择锁策略?
- 客户端/服务器应用:优先考虑悲观锁,因为可以保持连接
- Web应用:必须使用乐观锁,因为HTTP是无状态的
- 推荐方法:时间戳版本列法,既高效又能记录修改时间
- 遗留系统改造:校验和法侵入性最小
记住Oracle锁的关键特点:
- 事务是必要的,不要过早提交
- 行级锁没有额外开销
- 读不阻塞写,写不阻塞读
- 可以同时实现高并发和数据一致性
通过合理使用这些锁策略,你可以构建出既快速又可靠的数据库应用!
------------------作者介绍-----------------------
姓名:黄廷忠
现就职:Oracle中国高级服务团队
曾就职:OceanBase、云和恩墨、东方龙马等
电话、微信、QQ:18081072613
个人博客: (http://www.htz.pw)
CSDN地址: (https://blog.csdn.net/wwwhtzpw)
博客园地址: (https://www.cnblogs.com/www-htz-pw)