SQL Server 根据主键更新数据却使用Cluster Index Scan问题

项目很多job在同一时刻同时启动,结果一直发生死锁问题, 通过Sqlserver profiler 分析发现 似乎是2张表的insert 和 update 发生互锁, 大致情景如下:




 












通过sql server profiler 发现这里的update 需要在主键索引上加U锁但是却在等待另一个transaction的insert 的之后x 锁,update 是根据主键来更新的 不应该出现这种情况啊 , 后来在分析update语句的执行计划



[code="sql"](@P0 nvarchar(4000),..@P11 nvarchar(4000))UPDATE TBL_SR_MAST SET SR_NO =  @P0 , .. WHERE SR_ID =  @P11







Clustered Index Update(OBJECT:(...)





  |--Compute Scalar(..[Expr1012]=CONVERT_IMPLICIT(varchar(32),[@P10],0)))





       |--Top(ROWCOUNT est 0)





            |--Clustered Index Scan(OBJECT:(.. WHERE:(CONVERT_IMPLICIT(nvarchar(32),..,0)=[@P11]) ORDERED)



这里明明是主键更新,居然出现Clustered Index Scan 而不是 Cluster Index Seek, 所以导致等待另一个transaction 的 insert 的索引锁,后来发现sql server 查询语句参数化的时候如果参数的类型和表中字段类型不一致的时候就会发生Clustered Index Scan,而正常的使用jdbc的preparedstament的时候 是默认以unicode的方式向database 发送string的, sqlserver 会解析成ncarchar的数据库类型,就导致了这个问题。 最后是在



jdbc url 上加上sendStringParametersAsUnicode=false 参数( jdbc:jtds:sqlserver://....;sendStringParametersAsUnicode=false),解决了死锁问题。 但是这样改制后有个问题就是如果表中确实有nvarchar的字段可能会导致一些 问题或者 乱码。

猜你喜欢

转载自lovexifu2012.iteye.com/blog/1567548