Transaction 中執行多條SQL,與我用分隔符號
sql1;sql2;sql3 這樣的差異在於Transaction 的寫入發生錯誤時,是可以將目前已寫的SQL 復原
(roll-Rollback)當作沒發生過,要嘛全寫要嘛全都不寫。而用分隔符號的,即使寫到一半發生
錯誤,前面的依然也寫進去了。尤其是當你把表頭和表身分開紀錄時,只有在commit之後,
才會一起看的到表頭和表身。
/// <summary>
/// Postgresql Transaction
/// </summary>
/// <param name="list">sql</param>
/// <param name="connstr">ConnectionStr</param>
/// <returns></returns>
public bool TransactionDB(List<string> list, string connstr)
{
if (list.Count == 0)
{
return true;
}
NpgsqlTransaction tran = null; ;
NpgsqlCommand com = null;
NpgsqlConnection conn = null;
bool isCommit = true;
try
{
conn = new NpgsqlConnection(connstr);
//打開一個資料庫連接
conn.Open();
com = conn.CreateCommand();
//The IsolationLevel for this transaction. The default is ReadCommitted.
tran = conn.BeginTransaction(IsolationLevel.ReadCommitted);
for (int i = 0; i < list.Count; i++)
{
com.CommandText = list[i];
com.ExecuteNonQuery();
}
//Commit
tran.Commit();
}
catch (Exception eee)
{
isCommit = false;
try
{
if (conn.State == ConnectionState.Open)
{
//Rollback
tran.Rollback();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}
finally
{
if (com != null)
{
com.Dispose();
}
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
}
return isCommit;
}
比較值得注意的是這一行,這代表交易的隔離層次,如果不設定,則預設隔格層次就是
Read Committed:
tran = conn.BeginTransaction(IsolationLevel.ReadCommitted);
隔離層次主要是要處理當交易正在進行時,其他的查詢或交易動作是否可以讀寫資料,或取得的資料是不是已經完成交易或未完成交易的狀態。
- Read Uncommitted:允許其他查詢在交易未完成時,就可以讀取交易範圍內的資源,這個層次會鎖定的範圍非常小 (幾乎不定),在多人環境下可以完成忽略交易可能造成的損耗,但卻會有很嚴重的 Dirty Read 問題。
- Read Committed:只允許其他查詢讀取已認可 (Committed) 的交易資料,這個層次會在交易認可前鎖定資源,認可後就釋放,它的優點是鎖定範圍小,對效能影響不大,而且可以保證資料的修改是已認可的,但它卻有可能會發生幽靈讀取 (Phantom Read) 的狀況,且它也會有不可重覆讀取 (Nonrepeatable read) 的問題
- Repeatable Read:有時交易執行的範圍會很長,且可能在交易內重覆參考某些資源,這種時候如果外部交易修改了交易內的參考資源時,就會發生資料不一致的問題,而這個隔離層次就是在避免這個問題,它具有 Read Committed 的特性,但又不允許其他交易修改交易內參考到的資源,以保證資料是可重覆讀取 (Repeatable Read) 的。
- Serializable 演算法是最穩固的一種隔離層次演算法,因為它強制所有的交易都必須 按照順序,而且外部的查詢在 Serialize 的交易結束前,都不能讀取在交易中被鎖定住 的資源 (資料列或資料表),這對資料正確性的保障是最完整的,但它因為鎖定了大範圍的資源,會對多人環境的資料庫效能造成影響,死結 (deadlock) 的機率也會提高。
※Dirty Read:意指在交易外的查詢讀到的資料會不一致,這是因為交易在認可前被讀
了一次 (s1),交易中修改了該值,而修改後認可前又被讀了一次 (s2),而這兩個值不一
致 (s1 != s2)。
- Phantom Read: 意指在查詢讀到的資料在資料表中不存在,這會發生在 INSERT 和 DELETE 的狀況,例如交易進行時有新增資料或刪除資料,而外部查詢在交易完成前要查詢這筆新資料,或是在交易刪除資料後又可讀到被刪除的資料時,就是 Phantom Read 的錯誤狀態。
沒有留言:
張貼留言