数据库锁总结

数据库锁总结 一直想写一篇关于数据库锁的相关总结文章因为平时看数据库相关的博文的时候会时不时看到某个数据库锁一直没弄清楚各种锁的关系下面就大概总结一下数据库锁出现的原因是为了处理并发问题因为数据库是一个多用户共享的资源当出现并发的时候就会导致出现各种各样奇怪的问题就像程序代码一样出现多线程并发的时候如果不做特殊控制的话就会出现意外的事情比如“脏“数据、修改丢失等问题。所以数据库并发需要使用事务来控制事务并发问题需要数据库锁来控制所以数据库锁是跟并发控制和事务联系在一起的。平时会经常看到或者听到数据库锁有“共享锁”“排它锁”“互斥锁”“写锁”“读锁”“悲观锁”“乐观锁”“行级锁”“表级锁”“页级锁”等同时我们还会常看到“丢失修改“”不可重复读“”读脏数据“这三个术语他们究竟是什么关系以及怎么理解呢下面就来介绍一下他们。先说事务的特性要想成为事务必须满足ACID原子性一致性隔离性持久性四特性事务是恢复和并发控制的基本单位。原子性指的是事务是数据库的逻辑工作单位事务中操作要么都做要么都不做一致性指的是事务的执行结果必须是使数据库从一个一致性状态变大另一个一致性状态一致性和原子性是密切相关的隔离性指的是一个事务执行不能被其他事务干扰持久性指的是一个事务一旦提交他对数据库中数据的改变就是永久性的。先说悲观锁和乐观锁吧。并发控制一般采用三种方法分别是乐观锁和悲观锁以及时间戳。乐观锁认为一个用户读数据的时候别人不会去写自己所读的数据悲观锁就刚好相反觉得自己读数据库的时候别人可能刚好在写自己刚读的数据其实就是持一种比较保守的态度时间戳就是不加锁通过时间戳来控制并发出现的问题。悲观锁就是在读取数据的时候为了不让别人修改自己读取的数据就会先对自己读取的数据加锁只有自己把数据读完了才允许别人修改那部分数据或者反过来说就是自己修改某条数据的时候不允许别人读取该数据只有等自己的整个事务提交了才释放自己加上的锁才允许其他用户访问那部分数据。乐观锁就比较简单了就是不做控制这只是一部分人对于并发所持有的一种态度而已。时间戳就是在数据库表中单独加一列时间戳比如“TimeStamp”每次读出来的时候把该字段也读出来当写回去的时候把该字段加1提交之前 跟数据库的该字段比较一次如果比数据库的值大的话就允许保存否则不允许保存这种处理方法虽然不使用数据库系统提供的锁机制但是这种方法可以大大提高数据库处理的并发量因为这种方法可以避免了长事务中的数据库加锁开销操作员A 和操作员B操作过程中都没有对数据库数据加锁大大提升了大并发量下的系 统整体性能表现。 需要注意的是乐观锁机制往往基于系统中的数据存储逻辑因此也具备一定的局 限性如在上例中由于乐观锁机制是在我们的系统中实现来自外部系统的用户 余额更新操作不受我们系统的控制因此可能会造成脏数据被更新到数据库中。在 系统设计阶段我们应该充分考虑到这些情况出现的可能性并进行相应调整如 将乐观锁策略在数据库存储过程中实现对外只开放基于此存储过程的数据更新途 径而不是将数据库表直接对外公开。以上悲观锁所说的加“锁”其实分为几种锁分别是排它锁和共享锁其中排它锁又称为写锁共享锁又称为读锁。共享锁和排它锁是具体的锁是数据库机制上的锁存在以下关系x表示是排它锁(Exclusive)s表示共享锁(Share)Y表示yesN表示no上图表示可以共存的锁如第二行表示一个事务T1给某数据加了X锁则事务T2就不能再给那数据加X锁了同时也不能再加S锁了只有到T1事务提交完成之后才可以。默认来说当sql脚本修改更新某条记录的时候会给该条记录加X锁读的话加的是S锁。另外并发操作会导致数据的不一致性主要包括“丢失数据”“不可重复读”“读脏数据等。详细可看 王珊 版 数据库系统概论第十一章 并发控制。还有就是并发控制会造成活锁和死锁就像操作系统那样会因为互相等待而导致。活锁指的是T1封锁了数据RT2同时也请求封锁数据RT3也请求封锁数据R当T1释放了锁之后T3会锁住RT4也请求封锁R则T2就会一直等待下去这种处理方法就是采用“先来先服务”策略死锁就是我等你你又等我双方就会一直等待下去比如T1封锁了数据R1正请求对R2封锁而T2封住了R2,正请求封锁R1这样就会导致死锁死锁这种没有完全解决的方法只能尽量预防预防的方法有①一次封锁发指的是一次性把所需要的数据全部封锁住但是这样会扩大了封锁的范围降低系统的并发度②顺序封锁发指的是事先对数据对象指定一个封锁顺序要对数据进行封锁只能按照规定的顺序来封锁但是这个一般不大可能的。另外系统如何判断出现死锁呢毕竟出现死锁不能一直干等下去要及时发现死锁同时尽快解决出现的死锁诊断和判断死锁有两种方法一是超时法二是等待图法。超时法就是如果某个事物的等待时间超过指定时限则判定为出现死锁等待图法指的是如果事务等待图中出现了回路则判断出现了死锁。对于解决死锁的方法只能是撤销一个处理死锁代价最小的事务释放此事务持有的所有锁同时对撤销的事务所执行的数据修改操作必须加以恢复。锁包括行级锁和表级锁行级锁是一种排他锁防止其他事务修改此行在使用以下语句时Oracle会自动应用行级锁INSERT、UPDATE、DELETE、SELECT … FOR UPDATE [OF columns] [WAIT n | NOWAIT];SELECT … FOR UPDATE语句允许用户一次锁定多条记录进行更新使用COMMIT或ROLLBACK语句释放锁表级锁又分为5类行共享 (ROW SHARE) – 禁止排他锁定表行排他(ROW EXCLUSIVE) – 禁止使用排他锁和共享锁共享锁(SHARE) - 锁定表对记录只读不写多个用户可以同时在同一个表上应用此锁共享行排他(SHARE ROW EXCLUSIVE) – 比共享锁更多的限制禁止使用共享锁及更高的锁排他(EXCLUSIVE) – 限制最强的表锁仅允许其他用户查询该表的行。禁止修改和锁定表。