[杂]DeadLock, Isolation Level, EntityFramework

时间:2023-03-10 05:17:36
[杂]DeadLock, Isolation Level, EntityFramework

由于没有注意到EF事务的默认隔离级别是Serializable,(据说EF6.0以后默认隔离级别改成了Read_Commit_Snapshot)--这里有误,应该是加了TransactionScope以后的级别,EF默认应该是Read_Commit级别。 而后在Production环境中产生了很多Deadlock的错误。

[杂]DeadLock, Isolation Level, EntityFramework

重现

首先两个Session中分别执行个Update 获得X锁

[杂]DeadLock, Isolation Level, EntityFramework

[杂]DeadLock, Isolation Level, EntityFramework

可以通过语句查询锁的状态如下:

[杂]DeadLock, Isolation Level, EntityFramework

接着在非主键列上执行查询,查询计划是全表扫描

[杂]DeadLock, Isolation Level, EntityFramework

会发现第一个session中需要的资源980b829163df被占据,无法放置S锁

如果这个时候第二个session执行一次全表扫描的话,dead lock就诞生了。

[杂]DeadLock, Isolation Level, EntityFramework

分析

Serializable是一个并发性相当低的隔离级别,一般程序都不需要设置到这个级别。

问题代码:

[杂]DeadLock, Isolation Level, EntityFramework

在一个大的事务中有update获得X锁,同时又有未建立索引的全表扫描。

只要同时有两个Session获得了X锁,触发deadlock.

原因有好几个:

1 隔离级别太高

2 事务太复杂

3 并发度较高

解决方案

1 拆分事务

确定真的需要如此大的事务么

2降低隔离级别

读的部分采用read uncommit级别这里可以

3 在相应表上建立相应的非聚集索引,避免全表扫描的查询计划。