精通Hibernate——数据库系统锁的基本原理

来源:互联网 发布:ws848进入编程模式 编辑:程序博客网 时间:2024/06/07 06:14

锁的基本原理如下:
1、当一个事务访问某种数据库资源时,如果执行select语句,必须先获得共享锁,如果执行insert、update或delete语句,必须先获得独占锁,这些锁用于锁定被操纵的资源
2、当第二个事务也访问相同的资源时,如果执行select语句,也必须先获得共享锁,如果执行insert、update或delete语句,也必须先获得独占锁。此时根据已经放置在资源上锁的类型,来决定第二个事务应该等待第一个事务解除对资源的锁定还是立即获得锁。
如果资源上没有锁,第二个读事务立即获得共享锁,如果第二个事务是写事务,则立即获得独占锁
如果资源上有共享锁,第二个读事务立即获得共享锁,如果第二个事务是写事务,则需要等待第一个事务解除共享锁
如果资源上有独占锁,第二个事务无论是读还是写,都必须等待第一个事务释放独占锁。
数据库中的锁可以分为以下几种:
数据库级锁、表级锁、区域级锁、页面级锁(锁定数据库特定页面)、键值级锁(锁定数据库表中带有索引的一行数据)、行级锁。
数据库中的锁粒度会自动升级,例如:当一个事务中的锁较多,达到锁升级的门限时,系统自动将行级锁和页面级锁升级为表级锁。
按照封锁的程度可以分为 共享锁、独占锁、更新锁
共享锁
允许其他事务读取锁定的数据,但是不允许其他事务修改和删除
当一个事务select之后就把对应的数据加上了共享锁,在默认情况,当数据被读取后,数据库立即解除共享锁,如果数据资源上配置了共享锁,还能再配置共享锁和更新锁。他的并发性能良好,能支持多个事务读相同的数据,每个事务都能获得一把共享锁。
独占锁
又名排他锁,适用于修改数据场合,他锁定的数据不允许其他事务读取和修改
当一个事务insert、update、delete之后,数据库系统会自动对sql操纵的数据添加独占锁,独占锁一直到事务结束才会解除,独占锁不和其他锁兼容,如果已经配置了独占锁不能再添加其他锁。同理,如果一个资源已经有其他锁,就不能添加独占锁。并发性能比较差。
更新锁
更新锁在更新阶段用户锁定将要被更新的数据,这可以避免使用共享锁造成的死锁。例如:

update account set balance = 900 where id = 1;

如果使用共享锁,更新步骤如下:
1、获得一个共享锁,读取id=1的数据
2、将共享锁升级为独占锁,再执行更新操作
如果有两个或多个事务同时更新,他们同时将共享锁升级为独占锁,由于独占锁不兼容其他锁,因此每个事务都进入等待状态,等待其他事务释放锁,这就造成了死锁。
更新锁具有以下特征
当一个事务执行update时,数据库系统先为事务分配一把更新锁,当读取完毕执行更新操作时,会把更新锁升级为独占锁。
由于更新锁与共享锁兼容,但是一个资源最多只能放一把更新锁,当多个事务同时更新相同数据时,只有一个事务能获得更新锁,然后再把更新锁升级为独占锁,其他事务必须等到事务结束才能更新锁,这样避免了死锁。

下面说下死锁以及防止方法
数据库死锁是多个事务分别锁定一个资源,又试图请求锁定对方已经锁定的资源,例如,如果以下两个事务并发,就会产生死锁:
事务1

1.begin;2.update customer set name = 'tom' where id = 1;3.update orders set order_number = 'tom_001' where id = 1;

事务2

4.begin;5.update orders set order_number = 'jack_001' where id = 1;6.update customer set name = 'jack' where id = 1;

第一个事务当执行到第2行时,对id=1的customer加上了独占锁,此时,第二个事务执行到了第6行,对id=1的orders加上了独占锁;当第一个事务继续执行到第3行,发现id=1的orders已经被第二个事务加上了独占锁,因此,第一个事务会等待第二个事务释放该锁,当第二个事务执行到第6行时发现id=1的customer被一个事务加上了独占锁,他会等待第一个事务释放该锁,这样就形成两个事务一直再等待对方提交事务而释放锁,从而造成了死锁。
许多数据库能够定期自动搜索和处理死锁问题,当检测到死锁时,系统将结束死锁优先级最低的事务,并且撤销该事务。
防止方法
1、合理安排表的访问顺序
2、使用短事务
3、如果对数据的一致性要求不是很高,可以允许脏读,即:不需要对数据加锁
4、如果可能的话,错开多个事务访问相同资源的数据

0 0
原创粉丝点击