在一个事务中插入和更新时 Sql server 死锁

我正在使用 Azure SQL + Java + Spring Boot 2。目前我正在尝试了解死锁发生的原因。在事务中,我正在对同一张表但不同的行进行插入和更新。据我了解,SQL Server 默认使用rowlock和read_committed隔离。


这是死锁的详细信息:


<deadlock>

    <victim-list>

        <victimProcess id="process2b8618644e8"/>

    </victim-list>

    <process-list>

        <process id="process2b8618644e8" taskpriority="0" logused="352"

                 waitresource="KEY: 16:72057594043760640 (5f601e0257f1)" waittime="1321" ownerId="9246067"

                 transactionname="implicit_transaction" lasttranstarted="2019-02-17T13:03:49.683" XDES="0x2b868778458"

                 lockMode="U" schedulerid="2" kpid="288932" status="suspended" spid="118" sbid="0" ecid="0" priority="0"

                 trancount="2" lastbatchstarted="2019-02-17T13:03:49.793" lastbatchcompleted="2019-02-17T13:03:49.760"

                 lastattention="1900-01-01T00:00:00.760" clientapp="Microsoft JDBC Driver for SQL Server"

                 hostname="TZ-MacBook-Pro.local" hostpid="0" loginname="master" isolationlevel="read committed (2)"

                 xactid="9246067" currentdb="16" currentdbname="test" lockTimeout="4294967295" clientoption1="671088672"

                 clientoption2="128058">

            <executionStack>

                <frame procname="unknown" queryhash="0x431f2517c2d3feb8" queryplanhash="0x3a793ad664472011" line="1"

                       stmtstart="110" stmtend="238"

                       sqlhandle="0x02000000060c530e608cef3b3e4e4712f48c40d2efd9b04d0000000000000000000000000000000000000000">

                    unknown

                </frame>

                <frame procname="unknown" queryhash="0x0000000000000000" queryplanhash="0x0000000000000000" line="1"

                       sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">

                    unknown

                </frame>

            </executionStack>


此外,我在 id 列上使用了聚集索引,随机操作顺序没有问题。此外,当我只在事务中插入时,一切正常,没有死锁。 如果我切换到 PostgreSql,则不会出现死锁问题。


那么,为什么我在 Azure SQL 中遇到了死锁?


动漫人物
浏览 195回答 1
1回答

陪伴而非守候

死锁的一个常见原因是需要查询和索引调整的查询触及的数据多于必要的数据。死锁跟踪显示参数作为nvarchar(4000)数据类型传递。这可能会阻止有效使用列上的索引,varchar因为nvarchar它的数据类型优先级高于varchar.&nbsp;当从应用程序数据类型推断参数数据类型时,此问题尤其常见,因为字符串通常是 Unicode,例如在 Java 和 .NET 语言中,导致nvarchar参数与基础列数据类型无关。解决方案是对字符串使用 varchar 参数而不是 nvarchar,除非基础列是nvarchar.&nbsp;如果您不在nvarchar数据库中使用,请指定 JDBC 连接字符串参数sendStringParametersAsUnicode,如本答案中所述。或者,更改应用程序代码或框架配置以使用列的varchar参数类型varchar。最佳实践是确保参数与基础数据库列的类型相匹配。这将提高性能和并发性,并且还有其他好处。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java