共享锁与排它锁

共享锁【S锁】
又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。

排他锁【X锁】
又称写锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A。

共享锁与排它锁区别

1.共享锁只用于表级,排他锁用于行级。 
2.加了共享锁的对象,可以继续加共享锁,不能再加排他锁。加了排他锁后,不能再加任何锁。 
3.比如一个DML操作,就要对受影响的行加排他锁,这样就不允许再加别的锁,也就是说别的会话不能修改这些行。同时为了避免在做这个DML操作的时候,有别的会话执行DDL,修改表的定义,所以要在表上加共享锁,这样就阻止了DDL的操作。 
4.当执行DDL操作时,就需要在全表上加排他锁

上面都是一些概念性的东西,下面我从事务的隔离级别上讨论一下这两种锁:

事务有四大隔离级别(隔离级别由高到低):

(1)Serializable(串行化):一个事务在执行过程中完全看不到其他事务对数据库所做的更新(事务执行的时候不允许别的事务并发执行。事务串行化执行,事务只能一个接着一个地执行,而不能并发执行。)。
(2)Repeatable Read(可重复读):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,但是不能看到其他其他事务对已有记录的更新。
(3)Read Commited(读已提交数据):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,而且能看到其他事务已经提交的对已有记录的更新。
(4)Read Uncommitted(读未提交数据):一个事务在执行过程中可以看到其他事务没有提交的新插入的记录,而且能看到其他事务没有提交的对已有记录的更新。

他们到底实现了是么样的锁呢?我们一个一个看:

SERIALIZABLE(序列化)

 

添加范围锁(比如表锁,页锁等,关于range lock,我也没有很深入的研究),直到transaction A结束。以此阻止其它transaction B对此范围内的insert,update等操作。

 

幻读,脏读,不可重复读等问题都不会发生。

 

REPEATABLE READ(可重复读)

 

对于读出的记录,添加共享锁直到transaction A结束。其它transaction B对这个记录的试图修改会一直等待直到transaction A结束。

 

可能发生的问题:当执行一个范围查询时,可能会发生幻读。

 

READ COMMITTED(提交读)

 

在transaction A中读取数据时对记录添加共享锁,但读取结束立即释放。其它transaction B对这个记录的试图修改会一直等待直到A中的读取过程结束,而不需要整个transaction A的结束。所以,在transaction A的不同阶段对同一记录的读取结果可能是不同的。

 

可能发生的问题:不可重复读。

 

READ UNCOMMITTED(未提交读)

 

不添加共享锁。所以其它transaction B可以在transaction A对记录的读取过程中修改同一记录,可能会导致A读取的数据是一个被破坏的或者说不完整不正确的数据。

 

另外,在transaction A中可以读取到transaction B(未提交)中修改的数据。比如transaction B对R记录修改了,但未提交。此时,在transaction A中读取R记录,读出的是被B修改过的数据。

 

可能发生的问题:脏读。



阅读更多
个人分类: 数据库
上一篇Java transient关键字
下一篇Synchroniazed和Lock实现生产者--消费者
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭