笔记42-徐 锁产生的背景
笔记42-徐 锁产生的背景
1 --锁产生的背景 2 --事务是关系型数据库的一个基础概念。他是作为单个逻辑工作单元执行的一系列操作 3 --一个逻辑工作单元必须有4个属性,称为原子性,一致性,隔离性,持久性(ACID) 4 --只有这样才能成为一个事务 5 6 --原子性 7 --事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。 8 --比如一个事务要修改100条记录,要不就100条都修改,要不就都不修改。不能 9 --发生只修改了其中50条,而另外50条没有改的情况 10 11 --一致性 12 --事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须 13 --应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构 14 --(如B树索引或双向链表)都必须是正确的 15 16 17 --隔离性 18 --由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务识别数据所处的状态, 19 --要么是另一并发事务修改他之前的状态,要么是第二个事务修改他之后的状态,事务不会 20 --识别中间状态的数据。也就是说,虽然用户是在并发操作,但是,事务是串行执行的。 21 --对同一个数据对象的操作,事务读写修改是有先后顺序的。不是同一时间什么事情都能同时 22 --做的 23 24 --持久性 25 --事务完成之后,他对于系统的影响是永久性的。哪怕SQL发生了异常终止,机器掉电,只要 26 --数据库文件还是完好的,事务做的修改必须还全部存在 27 28 29 30 --以上事务的定义对所有的关系型数据库都成立,不管是SQLSERVER,还是DB2,ORACLE,都要 31 --遵从这些限制。但是,不同的数据库系统在事务的实现机制上有所不同,索引产生的效果在 32 --细节上是有差异的。尤其是SQLSERVER和ORACLE,在事务的实现上有很大不同。两者在不同的 33 --应用场景上各有优劣,不好讲谁做得更好,谁做得更差。下面讲的是SQLSERVER实现事务 34 --的方法 35 36 --要实现业务逻辑上的ACID,有两方面任务 37 38 --1、数据库程序员要负责启动和结束事务,确定一个事务的范围 39 --程序员要定义数据修改的顺序,将组织的业务规则用TSQL语句表现出来,然后将这些语句包括到 40 --一个事务中。换句话说,数据库程序员负责在必要并且合适的时间开启一个事务,将要做的操作 41 --以正确的顺序提交给SQLSERVER,然后在合适的时间结束这个事务 42 43 --2、SQLSERVER数据库引擎强制该事务的物理完整性 44 --数据库引擎有能力提供一种机制,保证每个逻辑事务的物理完整性 45 --SQLSERVER通过下面方法做到: 46 47 --(1)锁定资源,使事务保持隔离 48 --SQLSERVER通过在访问不同资源时需要申请不同类型锁的方式,实现了不同事务之间的隔离。 49 --如果两个事务会互相影响,那么在其中一个事务申请到了锁以后,另外一个事务就必须等待, 50 --直到前一个事务做完为止 51 52 --(2)先写入日志方式,保证事务的持久性 53 --SQLSERVER通过先写入日志的方式,保证所有提交了的事务在硬盘上的日志文件里都有记录。 54 --即使服务器硬件,操作系统或数据库引擎实例自身出现故障,该实例也可以在重新启动时使用 55 --事务日志,将所有未完成的事务自动地回滚到系统出现故障的点,使得数据库进入一个从事务 56 --逻辑上来讲一致的状态 57 58 59 --(3)事务管理特性,强制保证事务的原子性和一致性 60 --事务启动后,就必须成功完成,否则数据库引擎实例将撤销该事务启动之后对数据所做的所有 61 --修改 62 63 --如果一个连接没有提交事务,SQL会保持这个事务一直在活动状态,并且不在意这个事务 64 --的长短或这个连接是否还在活动,直到这个连接自己提交事务,或登出(logout)SQLSERVER 65 --如果在登出的时候还有未提交的事务,SQL会把这个事务范围内所做的所有操作撤销(回滚) 66 67 --所以,锁是SQL实现事务隔离的一部分,阻塞正是事务隔离的体现。要实现事务的隔离,阻塞 68 --不是SQLSERVER自找的,而是事务对SQLSERVER提出的要求,也是用户使用事务要付出的代价 69 --一个数据库开发者和DBA的工作,不是去消除阻塞,而是要把阻塞的时间和范围控制在一个 70 --合理的范围之内,使最终用户既能享受事务的ACID,又能享受预期的性能。完全消除阻塞, 71 --是不可能的事情 72 73 74 --换句话说,阻塞是实现事务的隔离所带来的不可避免的代价。为了达到良好的性能,数据库 75 --开发者和DBA要把阻塞的时间和范围控制在一个合理的范围之内。这不是一件很简单的工作, 76 --所以阻塞也将会是SQLSERVER的永恒的话题之一。做同样的事情,怎麽才能比较不容易产生 77 --大范围的阻塞呢? 78 79 --从下面3个方面着手 80 --1、申请资源的互斥度 81 --如果不同的连接申请的锁都是相互兼容的,那么他们就不会产生阻塞 82 83 --2、锁的范围和数目的多少 84 --做同样一件事情,SQLSERVER申请的锁的粒度和数目可能会不一样。一个良好设计的程序 85 --可以使申请的锁的粒度和数目控制在最小的范围之内。这样,阻塞住别人的可能性就能 86 --大大降低 87 88 --3、事务持有锁资源的时间长短 89 --如果一个锁是大家都需要用的,那么每个人持有他的时间越短,阻塞对性能的影响就会越小。 90 --最好是申请得越晚越好,释放得越早越好 91 92 --为了达到以上3个目的,需要研究一下SQLSERVER的锁资源模式和兼容性,以及他们怎麽被 93 --申请和释放的