所以,我們一直有這些死鎖問題,我想在一個簡單的代碼片段複製此。基本上,我們在進行一些處理之前先登錄我們的數據庫,然後更新結果。死鎖在單臺無交易(?)上更新或插入語句
數據庫是Sybase ASE的15.7,使用驅動程序的Adaptive Server Enterprise ODBC驅動程序(v15.05)。代碼是C#4.0
我用它來重現問題的代碼如下:
數據庫:
create table dbo.test_deadlock_t(
id int identity,
col1 int not null,
col2 varchar(255) not null,
constraint test_deadl_id_pk primary key clustered (id))
alter table test_deadlock_t lock allpages
C#(忽略了一些聲明性代碼的)
using System.Data.Odbc;
public const string cmdInsert = "INSERT INTO test_deadlock_t (col1, col2) VALUES (1, 'test') SELECT @@identity";
public const string cmdUpdate = "UPDATE test_deadlock_t SET col1 = 3, col2 = 'aaaaaaaa' WHERE id = {0}";
public static void Test()
{
Task[] tasks = new Task[threadCount];
for (int ii = 0; ii < threadCount; ii++)
{
tasks[ii] = Task.Factory.StartNew(() => InsertThenUpdate());
}
Task.WaitAll(tasks);
}
public static void Test2()
{
Task[] tasks = new Task[threadCount];
for (int ii = 0; ii < threadCount; ii++)
{
int ii_copy = ii;
tasks[ii_copy] = Task.Factory.StartNew(() => Update(ii_copy));
}
Task.WaitAll(tasks);
}
public static void InsertThenUpdate()
{
using (OdbcConnection connection = new OdbcConnection(connectionString))
{
connection.Open();
OdbcCommand command = new OdbcCommand(cmdInsert, connection);
int result = (int)(command.ExecuteScalar() as decimal?).Value;
Update(result);
}
}
public static void Update(int id)
{
using (OdbcConnection connection = new OdbcConnection(connectionString))
{
connection.Open();
OdbcCommand command = new OdbcCommand(String.Format(cmdUpdate, id), connection);
int result = command.ExecuteNonQuery();
Console.WriteLine("Update result : " + result);
}
}
兩個測試和測試2拋出隨機死鎖例外。我並不明確地啓動事務,表和查詢都很簡單,任何人都可以解釋發生了什麼以及如何避免這個問題?
謝謝!
編輯:本次測試的情況下,其實並不是真的重現問題,我編輯這個,因爲我有,當更新設置一個更大尺寸的VARCHAR列發生死鎖的感覺。
賈森mentionned,僵局可能會從PK索引的更新到來。一個可能的原因可能是查詢鎖定表,意識到頁面不夠用,將行移動到新頁面,然後嘗試鎖定索引以更新,同時在頁面上持有鎖定時,另一個查詢從查詢索引開始,然後要求在頁面上鎖定。
爲了測試完整性,如果您進行明確的事務處理,會發生什麼情況? – Ralf
我的猜測是它與此相關:http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.dc20021_1251/html/locking/locking7.htm。查看最後一段'在很多情況下,由所有頁鎖定導致的併發問題來自索引頁鎖,而不是數據頁本身的鎖。 –
@Ralf:我在之前的測試中失敗了(對於垃圾郵件抱歉),但行爲與顯式事務聲明基本相同。 – vpi