当数据库的并发访问量很大时,需要对数据库的锁的概念有一个清晰的了解,这样就能很好的处理数据库的大并发访问的问题
1.并发引起的问题
①脏读:包含未提交数据的读取。例如,事务1更改了某行。事务2 在事务1 提交更改之前读取已更改的行。如果事务1回滚更改,则事务2 便读取了逻辑上从未存在过的行。
②不可重复读取:当某个事务不止一次读取同一行,并且一个单独的事务在两次(或多次)读取之间修改该行时,因为在同一个事务内的多次读取之间修改了该行,所以每次读取都生成不同值,从而引发不一致问题。
③幻象:第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
④死锁:开两个查询窗口,分别执行下面两段sql就会引起死锁
--Query 1
Begin Tran
Update Lock1 Set C1=C1+1;
WaitFor Delay '00:01:00';
SELECT * FROM Lock2
Rollback Tran;
--Query 2
Begin Tran
Update Lock2 Set C1=C1+1;
WaitFor Delay '00:01:00';
SELECT * FROM Lock1
Rollback Tran;
2. 锁模式
①共享锁
共享 (S) 锁允许并发事务读取 (SELECT) 一个资源。资源上存在共享 (S) 锁时,任何其它事务都不能修改数据。一旦已经读取数据,便立即释放资源上的共享 (S) 锁,除非将事务隔离级别设置为可重复读或更高级别,或者在事务生存周期内用锁定提示保留共享 (S)锁。如 SELECT 语句
②排它锁
排它 (X) 锁可以防止并发事务对资源进行访问。其它事务不能读取或修改排它 (X) 锁锁定的数据。例如 INSERT、UPDATE或 DELETE
③更新锁
更新 (U) 锁可以防止通常形式的死锁。一般更新模式由一个事务组成,此事务读取记录,获取资源(页或行)的共享 (S)锁,然后修改行,此操作要求锁转换为排它 (X) 锁。如果两个事务获得了资源上的共享模式锁,然后试图同时更新数据,则一个事务尝试将锁转换为排它 (X)锁。共享模式到排它锁的转换必须等待一段时间,因为一个事务的排它锁与其它事务的共享模式锁不兼容;发生锁等待。第二个事务试图获取排它 (X)锁以进行更新。由于两个事务都要转换为排它 (X) 锁,并且每个事务都等待另一个事务释放共享模式锁,因此发生死锁。若要避免这种潜在的死锁问题,请使用更新 (U)锁。一次只有一个事务可以获得资源的更新 (U) 锁。如果事务修改资源,则更新 (U)锁转换为排它 (X) 锁。否则,锁转换为共享锁
3.事务隔离级别分为:
① READUNCOMMITTED:可以读未提交的数据,不发出锁
② READCOMMITTED:只读已提交的数据,遇到未提交的事务型数据时,则一直等待。发出共享锁,保持到读取结束
③ REPEATABLEREAD:是指可重复读,它的隔离级别要比ReadCommitted级别高。发出共享锁,保持到事务结束
④ SERIALIZABLE:锁定查询中使用的所有数据以防止其他用户更新数据。发出共享锁,保持到事务结束
事务隔离级别默认为:READCOMMITTED,设定的级别不同,存在的问题如下
隔离级别 | 脏读 | 不可重复读取 | 幻像 | 说明 |
未提交读(read uncommitted) | 是 | 是 | 是 | 如果其他事务更新,不管是否提交,立即执行 |
提交读(read committed默认) | 否 | 是 | 是 | 读取提交过的数据。如果其他事务更新没提交,则等待 |
可重复读(repeatable read) | 否 | 否 | 是 | 查询期间,不允许其他事务update |
可串行读(serializable) | 否 | 否 | 否 | 查询期间,不允许其他事务insert或delete |
4.在SQL Server的SQL语句中显式加锁
①NOLOCK:不发出锁。等同于READUNCOMMITTED ,用于Select语句
②HOLDLOCK:发出共享锁,保持到事务结束,事务内可更新。等同于SERIALIZABLE,用于Select语句
③XLOCK:发出排他锁,保持到事务结束,事务内可更新。用于Select语句
④UPDLOCK:发出更新锁,保持到事务事务结束,事务内可更新。(更新锁:不阻塞别的事物,允许别的事物读数据(即更新锁可与共享锁兼容),但他确保自上次读取数据后数据没有被更新).用于Select语句
⑤READPAST:发出共享锁,但跳过锁定行,它不会被阻塞。适用条件:提交读的隔离级别,行级锁,select语句中。
5.在SQL Server的SQL语句中显式控制锁的粒度
① ROWLOCK:强制使用行锁
②PAGLOCK:在使用一个表锁的地方用多个页锁
③TABLOCK:强制使用表锁
④TABLOCKX:强制使用独占表级锁,这个锁在事务期间阻止任何其他事务使用这个表
可和上面的命令联合使用
6.锁定数据库的一个表的区别
SELECT * FROM table WITH (HOLDLOCK) 其他事务可以读取表,但不能更新删除
SELECT * FROM table WITH (TABLOCKX) 其他事务不能读取表,更新和删除