让我们开始回答你的第一个问题。我没有索引 id = 1。
是的你是!!
让我们看一下 SQL Server 2014 CTP2 上的 Adventure Works 2012 数据库。这是我的笔记本电脑规格。
有一个表名 [AWBuildVersion]。它有一个聚集索引,就像你的表一样。在索引下,我们可以看到 PK 出现了。如果我们获取表的对象 id (sys.objects) 并查找索引 (sys.indexes) 的条目,我们可以看到索引位于位置 1。
简而言之,默认情况下主键是聚集索引。
http://technet.microsoft.com/en-us/library/ms177443(v=sql.105).aspx
好的,那么没有索引的表有什么?这些表称为堆。他们在位置 0 处确实有自己的索引,该索引指向第一个 IAM 页面。
http://technet.microsoft.com/en-us/library/ms188270(v=sql.105).aspx
下面的代码创建一个名为 [crafty] 的模式,并使用 SELECT INTO 将 [AWBuildVersion] 表复制到一个新模式。SELECT INTO 的好处是没有索引被结转。
use AdventureWorks2012
go
create schema [crafty] authorization [dbo];
go
select * into crafty.awbuildversion from dbo.awbuildversion
go
简而言之,我们可以看到在位置 0 处使用索引定义的堆。
那么什么是死锁,请求模式U是什么意思呢?
死锁是两个进程同时获取资源但顺序不同。简而言之,这两个过程都无法进行。引擎选择回滚时间最少的会话并终止该进程。
http://technet.microsoft.com/en-us/library/ms178104(v=sql.105).aspx
一张图片胜过千言万语!事务 1 抢资源 1。事务 2 抢资源 2。当他们试图抢对方资源时,就会产生死锁。
那么按键锁和用户模式U是什么意思呢?
要更新您的表格,您需要更新数据/索引页面。但是数据页实际上是表中的索引页(聚集索引)。SQL 引擎取出 (U)PDATE 锁。在实际更新期间,此锁将升级为排他锁 (X)。
当两个进程请求独占锁时,就有可能发生死锁。
为了完成这个主题,共享锁(SELECT)可以在不阻塞(同时)的情况下执行。通常一个进程从阻塞开始,然后当Engines死锁进程线程检测到循环图时变成死锁。
默认隔离级别为未提交读。
http://technet.microsoft.com/en-us/library/ms175519(v=sql.105).aspx
在这一点上,你有一个死锁。
你从这里去哪里?
1 - 可能有多个会话 (SPID) 运行相同的代码。为什么?你能改变这一点,使一次只有一个进程运行代码吗?
2 - 获取由 JDBC 生成的实际 TSQL。这可以通过 SQL 分析器和/或查看您的 DMV 来完成。
合并语句同时执行 UPDATE 和/或 INSERT。因此是复合操作。
3 - 你可以将隔离级别更改为可序列化吗?
http://technet.microsoft.com/en-us/library/ms173763.aspx
这将添加更多锁,并且可能会将您的死锁问题变为超时问题。请参阅 Kalen Daleny 文章,了解如何设置 LOCK_TIMEOUT。您将不得不调整您的代码以再次重试该操作,中间有一些延迟。
http://sqlmag.com/sql-server/inside-sql-server-controlling-locking
我希望这些信息对您有所帮助。
如果您需要更多帮助,请发布您的 TSQL。