数据库锁原理

1 为什么需要锁 
数据库通常有大量的用户在同时操作,所以并发的情况下需要控制对临界资源的操作,数据库通过锁来控制对临界资源的访问,从而保证数据的一致性。例如对于同一个账户,操作之前账户余额为1000,同时开始2个事务,一个事务取款100,一个事务往账户中汇入100,那么2个事务结束后,账户的余额必须还是1000,否则要么银行不干,要么个人不干。 
2 锁类型 
2.1 共享锁(读锁) 
读锁是共享的,互相不阻塞,也就是可以多个客户同时读取同一资源,而不互相干扰。 

加锁条件:当执行select时,数据库为这个事务分配一把共享锁,来锁定被查询的数据。 

解锁条件:默认情况下,数据被读取之后,数据库立即解锁。例如select * from table中,先锁定第一行,读取后,立即解锁第一行,然后再锁定第二行,这样大大降低锁争用程度。在repeatable read和serializable 这两种事务隔离级别下,共享锁是在事务结束时释放的,serializable对表加锁。 

2.2 排它锁(独占锁)(写锁) 
写锁是排他的,一个写锁会阻塞其他的读锁和写锁,只有这样才能保证同一时刻,只有一个用户能够写入,并阻止其他用户读取正在写入的同一资源。如果要锁定的数据资源,已经放置了其他的锁,则不能再放置排它锁。 

加锁条件:当执行insert update 和delete语句时,数据库会对操纵的资源使用排它锁。 

解锁条件:事务结束时解锁。 
3.锁原理 
锁的基本原理如下: 
1.当第一个事务访问数据库资源时,如果执行select语句,则必须先获得共享锁,如果执行insert update和delete时,必须获得排它锁 
2.当第二个事务也要访问相同的资源时,如果执行select语句,也必须先获得共享锁,如果执行insert update或者delete,也必须获得共享锁。根据已经放置在资源上的锁类型,来决定第二个事务是应该等待第一个事务释放锁,还是立即获得锁。 


 




4 锁粒度 
常见的锁有表锁、 行锁、 页锁、外键锁等。 

锁有一定的消耗,主要有:获得锁,检查锁是否已经解除,释放锁等,这些操作都会增加系统的开销。 

表锁开销比较小,但是并发性能也较差,行锁并发性能高,但是需要更多锁,数据库系统一般都支持锁的自动升级,例如一个事务中的锁过多的时候,可能会将行锁升级到表锁。 

mysql的各个存储引擎根据不同的应用场景采用不同的锁机制,MyISAM存储引擎采用表锁,InnoDB使用行锁。如果执行alert table之类的操作,服务器也会采用表锁,而忽略存储引擎的锁机制。 

页锁,某些数据库支持页锁,页锁粒度介于行锁和表锁之间,用于锁定存放数据的页,1页通常含有n个数据行。 


外键锁:外键会产生高级别的锁,后面介绍死锁的时候会提到。 
5.乐观锁和悲观锁 
悲观锁:假设如果不加锁就一定会出现问题。 
乐观锁:先假定不会出现并发问题,出现问题后再采取相应的措施。 

悲观锁通过select * from tbl for update实现。 
乐观锁可以在表中加一个version字段,每次更新的时候都+1,这样如果出现并发,第二次更新的时候version的值已经不再匹配,可以在这时采取相应的措施。 
6 死锁 
6.1 死锁是如何产生的 
同java的死锁一样,都是互相等待对方释放锁,造成了相互阻塞,造成的死锁。 

请看下面的表格: 


 

6.2 如何避免死锁 
1.修改操作表的顺序 
从上面的示例中可以看出,如果调整一下操作表的顺序就可以避免死锁。 

2.外键 
产生高级别的锁,会阻止其他事务操作或者其他DML操作,如果是因为外键产生的死锁,可以去掉外键约束,由应用来保证数据的完整性,通常生产环境都不建议加外键约束。 

3.短事务 
缩短事务的执行时间,可以减少锁的持有时间,可以降低死锁的风险。 





7 参考资料 
http://www.iteye.com/topic/743285 
http://www.iteye.com/topic/236271 
http://www.iteye.com/topic/170393 
http://thrillerzw.iteye.com/blog/1880242 
http://cfeers.iteye.com/blog/760992   * 
http://blog.sina.com.cn/s/blog_548bd2090100ir7k.html 
http://www.cnblogs.com/ggjucheng/archive/2012/11/14/2770445.html 
http://blog.163.com/qh_odd@126/blog/static/33376057200851625011100/ 
http://wenku.baidu.com/link?url=kS0uwo_ykqH5PJg7AM39Mf2jrZfOqn7gusgJkf8s2kJShOr-n_9CiykvDqzEIoHxYkokG_XY7keyu6OL-Bn_R4pw3xW1pN0IUNbYxNrdu3q 
《精通hibernate》 
《高性能MySQL》

from   http://frank1234.iteye.com/blog/2164649

猜你喜欢

转载自aoyouzi.iteye.com/blog/2164731