长久以来,对数据库的各种隔离机制一直很模糊,总搞不清楚在别人眼里很简单的锁机制,事务隔离机制,最近查了一些资料,把自己对数据库的一些理解写下来,权当笔记,不对的地方希望大家指正。
为了确保并发用户在存取同一数据库对象时的正确性(即无丢失修改、可重复读、不读“脏”数据),数据库中引入了锁机制:
从数据库角度来说,数据库一般情况下会有以下两种锁类型:
1.排它锁(X锁):若事务T对数据D加X锁,则其它任何事务都不能再对D加任何类型的锁,直至T 释放D 上的X 锁;一般要求在修改数据前要向该数据加排它锁,所以排它锁又称为写锁,被写锁锁定的记录可以被无锁读取,比如在oracle中没有读锁的概念,在sqlserver中可以使用with nolock。
2.共享锁(S锁):若事务T对数据D加S 锁,则其它事务只能对D加 S锁,而不能加X 锁,直至 T 释放D 上的S 锁;一般要求在读取数据前要向该数据加共享锁,所以共享锁又称为读锁。
说明:因为任务事务在读取或者更改一条数据之前,都需要先申请相应的锁类型,所以一旦加上写锁,则其它事务只能等待该事务完成后才能申请相应的锁。一旦加上读锁(共享锁),则别的事务还可以对相同的数据申请共享锁,可以对数据进行读取,则不能修改,无锁读取在sqlserver 中可以使用select ...from ....with nolock。在oracle没有读锁概念。
其它锁概念:
悲观锁:指对于外界对数据的修改持保守态度,为了保持数据被操作的一致性,于是对数据采取了数据库层次的锁定状态,依靠数据库提供的锁机制来实现。该锁只是基于以上数据库提供的锁实现。
乐观锁:与“悲观锁”正好相反,该锁机制认为数据资料的存取很少发生冲突,采取了宽松的锁机制,一般情况下,乐观锁由开发者自行实现,一般情况下,开发者为数据库需要乐观锁的表增加一个版本字段或者时间戳字段,若记录要修改,则增加该记录的版本字段,在提交时与原数据进行比较,若大于则说明可以正常提交,否则说明该记录已经被修改,需要进行检查。时间戳也同样。
悲观锁说明:比如事务T1通过SQL语句"Select user.name from user as user where user.ID=1 for update"来查找记录,则此时满足条件的记录全部被锁定,若事务T2通过SQL语句“Selct user.name from user where user.ID=1 for update”,则事务T2只能等式待事务T1完成后才能执行。
在数据库原理中,又可以把读锁和写锁分为长锁和短锁:
长锁:在整个事务范围内,该锁都有效。比如事务T1中有对数据D1的长写锁,则表示在T1整个事务过程中,别的事务都无法取得对数据D1的更新权限,直到事务T1完成提交或者回滚。
短锁:只在数据查询的更新等操作时有效,数据操作完毕马上释放。释放完毕后,别的事务即可以申请对该数据的锁。
谓词锁:锁定满足查询条件
数据库的标准隔离级别及锁定义:
隔离级别 |
记录上的写锁是长期的 |
记录上的读锁是长期的 |
谓词上的读锁和写锁是长期的 |
Read Uncommitted |
否 |
无读锁 |
无谓词锁 |
Read Committed |
是 |
否 |
短期读谓词锁 长期写谓词锁 |
Repeatable Read |
是 |
是 |
短期读谓词锁 长期写谓词锁 |
Serilizable |
是 |
是 |
长期读谓词锁 长期写谓词锁 |
Read Uncommitted:标准定义中,在该级别中不允许存在更新操作,也就是说在该级别的所有事务都是只读的,但是这种级别允许读取别的事务已经更改但还没有提交的数据,这样就会导致脏读。比如事务A更改了user的用户名为userA,但是还未提交,但此种级别的事务B读取了该数据,但是事务A又失败了,导致回滚,这样事务B其实读到了无用的中间数据。
Read Committed:该级别会导致两种错误读取:
1.不可重复读取:假设事务A已经读取了某条数据,因为是短期读锁,导致事务A释放对数据的锁,此时事务B申请到了对事务A已经读取事务的写锁,并更改数据并提交,当事务A再次读取该数据时,数据已经改变。
2.更新丢失:比如事务A和事务B同时读取了某条数据,初始值都是100,事务A的意图是在100的基础上加上40,得到结果140,事务B的意思是在这条数据上增加50,按照正常的模式,得到的最终值应该是190,但是由于数据事务A和B都读到的是初始数据,事务A提交后,此时该数据应该是140,但是B已经读取了旧数据100,然后B再更新,导致结果150,这样就产生了错误的结果,序列如下:r1(a,100)r2(a,100)w1(a,140)c1 w2(a,150)c2,其中r1表示事务A的读,W1表示事务A的写,B也同样。
Repeatable Read:在该隔离机制下,屏蔽了以上会出现的问题。但是该级别使用了短期的读谓词锁,这样会导致幻像读取,比如事务A读取了ID>0的所有记录。数据库可能需要装入整装表逐个遍历该张表的所有记录,完成每一条记录的读取和where条件的比对,然后谓词读锁释放,但当此时,事务A未提交事务,此进事务B插入了一条数据满足ID>0,但是因为事务A已经释放了ID>0的谓词锁,会导致检测不到事务B的提交数据。这种幻像读在Serilizable中可以去除,因为在Seriliable中,使用了长期读谓词锁,这样事务B插入数据时,会导致锁冲突,从而避免了幻像读取。
以上只是本人对数据库的一些简单理解,如果有什么不正确的地方,欢迎大家指正。
分享到:
相关推荐
数据库系统原理学习笔记 数据库系统原理学习笔记 数据库系统原理学习笔记
软考数据库工程师202038号学习笔记,重点知识都有标红。共有148页非常详细;软考数据库工程师202038号学习笔记,重点知识都有标红。共有148页非常详细软考数据库工程师202038号学习笔记,重点知识都有标红。共有148...
原创的数据库原理入门知识学习笔记,图文并茂,便于初学数据库的小伙伴了解相关知识。对数据库的视图等知识到数据库的完整性约束之前的内容进行讲述。
我的数据库原理及应用学习笔记.docx我的数据库原理及应用学习笔记.docx我的数据库原理及应用学习笔记.docx我的数据库原理及应用学习笔记.docx我的数据库原理及应用学习笔记.docx我的数据库原理及应用学习笔记.docx我...
数据库系统工程师学习笔记 非常有用!个能总结心得
编程学习笔记(数据库,C#)编程学习笔记(数据库,C#)编程学习笔记(数据库,C#)编程学习笔记(数据库,C#)编程学习笔记(数据库,C#)编程学习笔记(数据库,C#)编程学习笔记(数据库,C#)编程学习笔记(数据库,C#)...
数据库学习笔记
2009数据库系统工程师学习笔记 2009数据库系统工程师学习笔记
MySQL数据库学习笔记.pdfMySQL数据库学习笔记.pdfMySQL数据库学习笔记.pdfMySQL数据库学习笔记.pdfMySQL数据库学习笔记.pdfMySQL数据库学习笔记.pdf
MySQL数据库学习笔记 自己细心总结的 希望对大家有用
数据库——甲骨文学习笔记
数据库笔记
自己学习数据库系统工程师所做的笔记,主要的考点都在里面,特别是重点部分,有标红。本人上午72分下午60分通过,有需要的可以下载参考
DB2数据库学习笔记,转网上其他朋友的资源,感谢。
Oracle数据库体系结构-学习笔记,经过整理梳理让你比较清楚的学习整个Oracle体系
这个资源是针对于大学学习中的数据库的课程学习笔记
包含了mysql、sqlserver、oracle等主流数据库的学习笔记,尤其是韩顺平老师额oracle笔记,很详细哦。
作者学习数据库系统工程师所做的笔记,主要的考点都在里面,特别是重点部分,有标红。本人上午72分下午60分通过,有需要的可以下载参考
oracle学习笔记;oracle DML数据库操作语言;oracle常用函数使用方法及使用例子,存储过程等的创建