数据库锁:乐观锁和悲观锁,共享锁和排它锁,行级锁和表级锁

2018年9月11日 0 条评论 69 次阅读 0 人点赞

一、悲观锁和乐观锁

我们经常在开发中遇到数据库并发处理时,处理不一致的问题。需要对程序做并发控制。
典型的并发时出现的冲突有两种:
1、丢失更新:一个事务的更新覆盖了其它事务的更新结果,就是所谓的更新丢失。
例如X=0  A1把X=X+1  A2也设置X=X+1    如果A1和A2同时执行,可能出现最终X=1的情况。而我们需要得到的是X=2  。   这就需要update处理为串行化的。
2、脏读:读到的数据可能是旧的。    初使X=0    A1把X设置为1,A2读取时X是1,但A1后面又修改成了2,或回滚到了0,那么A2读取的数据就是脏数据。
A2读取的是未提交的数据。一般数据库不会设为读未提交,所以一般不会出现脏读。

那什么是乐观锁,什么是悲观锁。

悲观锁:需要使用数据库的锁机制,如数据库有表级排它锁,有行级排它锁。
假定一切操作都可能发现并发冲突,所以采取悲观态度。通过加锁,屏蔽一切可能违反数据完整性的操作
比方select * from table for update;  就是表锁,
select * from table where x = 1 for update; 就是行锁。
当使用for update后,其它会话还是可以执行select操作,但无法执行select xx for update操作,只有当前会话commit后,其它for update操作才会被执行。
典型例子可以参考quartz集群的锁机制:http://blog.itpub.net/11627468/viewspace-1764753/
当然,此时也不可以update,update需要等select xx for update 所在会话commit后才能执行。
注:mysql需要设置autocommit=0

乐观锁:其实不是真实的去锁住记录不让访问,或者不让更新。
假定操作很少发生冲突,一般对于读多写少的情况。只在提交操作时检查是否违反数据完整性。乐观锁不能解决脏读的问题。
可以通过版本号是否比上个版本号或者时间戳来实现。
对于冲突检测后的处理,需要业务逻辑去处理。

二、排它锁和共享锁
在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。
当数据对象被加上排它锁时,其他的事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取,但不能修改。
数据库利用这两种基本的锁类型来对数据库的事务进行并发控制。

三、表级锁和行级锁

DML锁的目的在于保证并发情况下的数据完整性,主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。
当Oracle执行DML语句时,系统自动在所要操作的表上申请TM类型的锁。当TM锁获得后,系统再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志,而只需检查TM锁模式的相容性即可,大大提高了系统的效率。TM锁包括了SS、SX、S、X等多种模式,在数据库中用0-6来表示。不同的SQL操作产生不同类型的TM锁。

lyssom

这个人太懒什么东西都没留下

文章评论(0)