========================== 在不同事务中,对表的操作顺序要一致,可防止死锁的产生 ====================== INSERT是对表锁定的,在一个线程对表进行INSERT时,另一个线程对表UPDATE时,若此时表还被之前的INSERT锁住时,UPDATE就没办法进行 ------------------------- 注意事务中最好不要使用锁定(类似select for update);否则粒度太大很容易出现lockwaitTimeOut -------------------------------- 我们看看p1的执行计划。怎么看呢?可以执行set statistics profile on,这句就可以了 --------------------------------- READ COMMITTED 隔离级别通过发布共享锁确保 SELECT 语句永远不读取未提交的数据。
对于同一个资源,共享锁与排它锁互不兼容,请求者在发布共享锁之前必须等待排它锁释放。 每个连接对于插入的数据都设置了排它锁,因此尝试读取对方插入数据的 SELECT 语句将试图解除插入数据的共享锁,但它会被阻塞。 两个连接将互相阻塞,从而形成一个死锁。 SQL Server 的锁定管理器检测到死锁时,将中止其中的一个批处理,回滚它的事务,释放它的阻塞锁,以便其他事务能够完成。作为死锁牺牲品的事务将回滚,其他事务则将成功完成。
SQL Server 2005 也提供帮助解决死锁问题的其他方法, 例如 SNAPSHOT ISOLATION 级别和用于 READ COMMITTED 的新选项(称为 READ COMMITTED SNAPSHOT)。 然而,这一事实 — 现在,通过 SQL Server 2005,您能够对事务进行编码并捕获死锁错误(并重试它们) — 已经意味着您拥有一个可任意支配、功能更加强大的工具。
------------------------------------ SQL Server 锁类型 在数据库中主要存在两种锁: S(共享锁)和X(排他锁) S(共享锁):在执行查询数据时,SQL server会将行锁定,这时只能查询数据,删,改被阻塞, X(排他锁):在插入和删除数据时,将行锁定,这时增,删,改都被阻塞 ---------------------------------------------- NOLOCK 等同于 READUNCOMMITTED ------------------------------------------------ 隔离级别: READ UNCOMMITTED 指定语句可以读取已由其他事务修改但尚未提交的行。
在 READ UNCOMMITTED 级别运行的事务,不会发出共享锁来防止其他事务修改当前事务读取的数据。READ UNCOMMITTED 事务也不会被排他锁阻塞,排他锁会禁止当前事务读取其他事务已修改但尚未提交的行。设置此选项之后,可以读取未提交的修改,这种读取称为脏读。在事务结束之前,可以更改数据中的值,行也可以出现在数据集中或从数据集中消失。该选项的作用与在事务内所有 SELECT 语句中的所有表上设置 NOLOCK 相同。这是隔离级别中限制最少的级别。
在 SQL Server 中,您还可以使用下列任意一种方法,在保护事务不脏读未提交的数据修改的同时尽量减少锁定争用:
***** READ COMMITTED 隔离级别,并将 READ_COMMITTED_SNAPSHOT 数据库选项设置为 ON。********
SNAPSHOT 隔离级别。 -------------------------------------------------- READ COMMITTED 指定语句不能读取已由其他事务修改但尚未提交的数据。这样可以避免脏读。其他事务可以在当前事务的各个语句之间更改数据,从而产生不可重复读取和幻像数据。该选项是 SQL Server 的默认设置。
READ COMMITTED 的行为取决于 READ_COMMITTED_SNAPSHOT 数据库选项的设置:
如果将 READ_COMMITTED_SNAPSHOT 设置为 OFF(默认设置),则数据库引擎会使用共享锁防止其他事务在当前事务执行读取操作期间修改行。共享锁还会阻止语句在其他事务完成之前读取由这些事务修改的行。共享锁类型确定它将于何时释放。行锁在处理下一行之前释放。页锁在读取下一页时释放,表锁在语句完成时释放。
当 READ_COMMITTED_SNAPSHOT 数据库选项设置为 ON 时,您可以使用 READCOMMITTEDLOCK 表提示为 READ COMMITTED 隔离级别上运行的事务中的各语句请求共享锁,而不是行版本控制。 ------------------------------------------------------ SNAPSHOT 指定事务中任何语句读取的数据都将是在事务开始时便存在的数据的事务上一致的版本。事务只能识别在其开始之前提交的数据修改。在当前事务中执行的语句将看不到在当前事务开始以后由其他事务所做的数据修改。其效果就好像事务中的语句获得了已提交数据的快照,因为该数据在事务开始时就存在。
除非正在恢复数据库,否则 SNAPSHOT 事务不会在读取数据时请求锁。读取数据的 SNAPSHOT 事务不会阻止其他事务写入数据。写入数据的事务也不会阻止 SNAPSHOT 事务读取数据。 ----------------------------------------------------------- session.connection().setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
String sql = "SELECT foo.* FROM my_table foo (nolock) WHERE foo.bar = :bar" Query query = cpdsEntityManager.createNativeQuery(sql, Foo.class); query.setParameter("bar", MyEnum.BAR); List<Foo> results = query.getResultList(); ----------------------------------
|