1,锁发生在事务中。事务的4个属性是:原子性,一致性,隔离性,持久性。(ACID)
1)原子性:对于数据的修改,要么全部执行,要么全部不执行,不存在一部分修改而另一部分未变的情况,即使执行一半发生断电的情况,下次启动时也会读取日志将上次未完的操作执行下去(故对于事务,日志优先写入)。
2)隔离性:对于数据的修改,同一时间只能由一个事务处理
3)一致性:事务完成时,必须使所有数据都保持一致状态。
4)持久性:事务完成之后,它对于系统的影响是永久性的。
2,隔离级别:mssql通过对共享锁申请和释放机制的不同处理,实现不同事务隔离级别。
1)隔离等级:
隔离级别 是否申请共享锁 何时释放 有无范围锁
未提交读 否 无 无
已提交读 是 当前语句执行完 无
可重复读 是 事务提交时 无
可序列化 是 事务提交时 有
在事务里面:
未提交读就是你读的同时我可以读写
已提交读取就是你读时我也可以读,但你读完后我才可以写,读操作共享锁时间一直到读取结束。
可重复读:事务提交时我才能写,读操作共享锁时间一直到事务结束。
注:未提交读:允许脏读,因此一个事务可能看见其他事务所做的尚未提交的更改。
已提交读:允许事务读取另一个事务以前读取(未修改)的数据,而不必等待第一个事务完成。 数据库引擎保留写锁(在所选数据上获取)直到事务结束,但是一执行 SELECT 操作就释放读锁。 这是数据库引擎默认级别。
已提交读快照:与未提交读一样,不加锁,但在事务未提交时,不能读取刚修改的数据,而是读取事务修改前的数据。
nolock等同于未提交读
参考msdn 设置隔离级别
2)默认隔离级别是已提交读
3)设置隔离级别:
SET TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED
| READ COMMITTED
| REPEATABLE READ
| SNAPSHOT
| SERIALIZABLE
}
[ ; ]
BEGIN TRAN
…
COMMIT
4)SELECT中设置NOLOCK,可以让mssql不去申请共享锁(S), 不过可能把没有提交事务的数据也显示出来,若之后事务回滚,select就会出现脏数据。
3,锁的类型:读锁(共享锁),申请修改锁(U),修改锁(X)
1共享(S):用于读取操作,如SELECT
2)更新(U):申请修改资源,做申请者登记,当资源释放时,可以第一个修改资源,它用于可更新的资源中,数据真正修改时再转化为排他锁。一次只有一个事务可以获得资源的更新锁(U 锁)。如果事务修改资源,则更新锁(U 锁)转换为排他锁(X 锁)。在已提交读级别以下(包含已提交读),因为共享锁在语句执行完之后就会释放,故先得到U锁的事务能接着转化为共享锁。在已提交读级别以上,更新锁作用不大,假设两个事务对同一资料都获取了共享锁,都执行更新操作,那么在事务结束前因都不会释放,故U锁将一直等待,转化不成排它锁进行修改,故会出现死锁。
3)排他(X):用于数据修改操作,如INSERT,UPDATE,DELETE
4)意向(I):用于建立锁的层次,一般是父层次,它有三种类型,意向共享(IS),意向排他(IX),意向排他共享(ISX)。
5)架构(SCH):包含两种类型,架构修改(Sch-M),架构稳定(Sch-S)
6)大容量更新。
7)键范围。
注:意向锁,锁定表或页,用它可以提高性能。原因:假设去桃花源景点,规定只有桃花源内无游客是,才允许下一位游客进入。现在来了一位新游客,判断是否他应该进入景点。方法有二:1,派景区管理员进入桃花源,在景区的山山水水排查,全部排查一遍,若无游客,则安排下一游客进入,若有,则下一游客等待。2,当前一游客进入时,将景区是否有游客进入状态设为TRUE,否则为False,那么当下一游客申请进入景区是,可以非常容易的判断出是否可以进入。 由这个问题知,方法2性能高一些。意向锁就相当于这个作用,当查询数据时,将数据所在的页或表设置为再用,以避免申请其他锁时的大范围判断。故知:意向锁可以提高性能,因为数据库引擎仅在表级检查意向锁,确定事务是否能安全的获取该表上的锁,而不需要检查表上的每行或每页。
8)锁与锁的申请:读与修改互斥,即若资源上现有共享锁,那么不能加排它锁,可加读锁,申请修改锁。若资源上有修改锁(X),那么不能读,也不能申请申请修改锁(U),换句话说,S锁与U锁是相互兼容的,但都与X锁不兼容。
9)可以加锁的资源分类:(1)RID,用于锁定堆上的某一行。(2)KEY:索引上的一行,或某个索引键。(3):数据页或索引页。(4):包含所有数据和索引的整个表。(5):DATABASE:整个数据库