sql server 2008学习12 事务和锁
事务
事务的点:
1.begin tran
是事务开始的地方,也是 事务回滚的起点.也就说他会忽略这个起点之后的最终没有提交的所有语句,
2.commit tran
事务的提交 是一个事务的终点
当发出 commit tran命令时,可以认为 该事务是 持久的.
撤销已完成事务的唯一方法 是 发出一个新的事务.从功能上而言,该事务 是对第一个事务的反转.
3.rollback tran
事务回滚到 begin执行之前的状态. 不过也有例外,也可以 使用 保存点.
4.save tran
保存事务从本质上说就是创建书签. 为书签起个名字,就是在回滚中 引用它.
创建书签的好处就是 可以 回滚到代码中的特定位置.
注意: rollback之后会清楚所有的保存点..
事务全部是关于原子性的.
sql server 的日志工作方式:
在数据库的正常操作中,大多数执行的活动都是 “记录”在 事务日志上,而非直接写入数据库中.
检查点 是指 强制把数据库现在所使用的脏页 写入磁盘的周期性操作
脏页 一些在读入到缓存后 已经被修改,但是所进行的修改还没有写入到磁盘的日志或数据页.
写入日志的过程
锁和并发:
SQL Server锁类型(SQL)收藏 1. HOLDLOCK: 在该表上保持共享锁,直到整个事务结束,而不是在语句执行完立即释放所添加的锁。 2. NOLOCK:不添加共享锁和排它锁,当这个选项生效后,可能读到未提交读的数据或“脏数据”,这个选项仅仅应用于SELECT语句。 3. PAGLOCK:指定添加页锁(否则通常可能添加表锁)。 4. READCOMMITTED用与运行在提交读隔离级别的事务相同的锁语义执行扫描。默认情况下,SQL Server 2000 在此隔离级别上操作。。 5. READPAST: 跳过已经加锁的数据行,这个选项将使事务读取数据时跳过那些已经被其他事务锁定的数据行,而不是阻塞直到其他事务释放锁,READPAST仅仅应用于READ COMMITTED隔离性级别下事务操作中的SELECT语句操作。 6. READUNCOMMITTED:等同于NOLOCK。 7. REPEATABLEREAD:设置事务为可重复读隔离性级别。 8. ROWLOCK:使用行级锁,而不使用粒度更粗的页级锁和表级锁。 9. SERIALIZABLE:用与运行在可串行读隔离级别的事务相同的锁语义执行扫描。等同于 HOLDLOCK。 10. TABLOCK:指定使用表级锁,而不是使用行级或页面级的锁,SQL Server在该语句执行完后释放这个锁,而如果同时指定了HOLDLOCK,该锁一直保持到这个事务结束。 11. TABLOCKX:指定在表上使用排它锁,这个锁可以阻止其他事务读或更新这个表的数据,直到这个语句或整个事务结束。 12. UPDLOCK :指定在读表中数据时设置更新 锁(update lock)而不是设置共享锁,该锁一直保持到这个语句或整个事务结束,使用UPDLOCK的作用是允许用户先读取数据(而且不阻塞其他用户读数据),并且保证在后来再更新数据时,这一段时间内这些数据没有被其他用户修改。
锁 是 一种防止在某对象执行动作的一个进程 于已在该对象上执行的其他进程 相冲突的机制.
通过锁可以防止的问题:
- 脏读
- 非重复性读取
- 幻读
- 丢失更新
1.脏读
如果一个事务读取的记录 是另一个未完成事务的一部分,那么这时 就发生了脏读.
如果第一个事务正常完成,那么就没问题.如果回滚的话,那将从数据库看来从未发生的事务中获取信息.
2.非重复性读取
如果一个事务中两次读取记录,而另一个事务在这期间改变了数据,就会发生 非重复性读取.
3.幻读
就update数据的同时有人执行insert语句.
4.丢失更新
同时又两个事务,都在更新一条数据,
其中一个更新数据完毕退出了.这是 另一个事务才开始更新此条数据,那么就导致 第一个事务做的更新 丢失了.
可以锁定的资源:
- 数据库
- 表,锁定整个表,包括 实际的数据行,以及与表相关联的所有索引中的键.
- 区段
- 页: 该页上的数据或索引键
- 键:在索引中的特定键或一系列的键. 相同索引页的其他键不受影响.
- 行或RID
锁定模式
- 共享锁: 这是最基本的一种锁.可以防止用户执行脏读.
- 排他锁:不与其他任何锁兼容, 这可以防止两个人同时 更新,删除 或执行任何操作.
- 更新锁:是一种特殊的占位符. 考虑一下: 为了执行 update,需要验证where子句来指出想要更新的具体行,这需要一个共享锁,
,直到真正进行物理更新的时候,需要一个排它锁.
这说明,更新操作 有一下两个不同的阶段:
1)指出满足where子句条件的内容,该查询有个 共享锁
2)决定执行更新,那么锁 升级为 排它锁..否则,将锁转换为 共享锁.
如果没有更新锁,死锁就会一直出现.两个更新查询会在 共享模式下运行.
a完成了它的查询工作,并准备进行物理更新.它想升级为排它锁.他是不可以这么做,因为b正在完成查询.除非b需要进行物理更新,否则它会完成查询. 为了做到这点,b必须升级为排它锁,但是不能这么做,因为a正在等待.
4.意向锁
是真正的占位符,它用来处理对象层次问题.
假设一下,已对某一行建立了锁,但是有人想在页上或区上 建立锁,那么您肯定不愿意.
如果没有意向锁,那么较高层次的对象将不会知道较低层次上有锁.意向锁可改进性能,因为sql server 只需要在表层上检查意向锁,以此来决定事务 是否可以 安全地 锁定整个表.
意向锁分为以下三种类型:
- 意向共享锁:该意向锁指 已经或者将要在层次结构的一些较低点处建立共享锁.
- 意向排他锁:
- 共享意向排它锁:它指已经或将会在 对象层次结构下面建立共享锁,但目的是为了修改数据.会在某个时刻称为排它锁.
5.模式锁
分为以下两种:
- 模式修改锁(Sch-M): 对对象进行模式改变, 在 模式修改锁 之间,不能对 对象进行查询或其他操作.
- 模式稳定性锁定(Sch-S):与共享锁类似, 这个锁唯一目的就是 防止Sch-M.
6.批量更新锁(BU)
允许并行加载数据.
设置隔离级别:
使用 set transaction isolation level 级别
1.read committed
通过 read committed , 任何创建的共享锁 将在创建它们的语句完成后 自动释放.
2.read uncommitted
是所有隔离级别选择中最危险的.但是他在速度方面有最好的性能.
设置 该级别,将告诉sql server 不要设置任何锁,也不要实现任何锁.
3.pepeatable read
会稍微地 将隔离级别升级,并提供一个额外的并发保护层.不仅能防止脏读,而且可以防止非重复性读取.
4.serializable
该锁 是堡垒级 的隔离级别. 除了丢失更新意外,它防止所有形式的并发问题.甚至能防止幻读.
4.snapshot
是最新的一种隔离级别. 只有为 数据库打开 allow_snapshot_isolation , 该级别才可用.