Three possible problems of concurrency
Dirty read
Definition: During the execution of transaction A, transaction B reads the modification of transaction A, but transaction A does not end (COMMIT). Transaction A may succeed or fail later.
Metaphor: A modified the source code and did not submit it to the source code system. A sent the code to B directly through QQ. A then canceled the modification.
Sample Code
Copy codeThe Code is as follows: [TestMethod]
Public void dirty read _ test ()
{
// Prerequisites
Using (var context = new TestEntities ())
{
Assert. AreEqual (1, context. Tables. Count ());
}
Var autoResetEvent = new AutoResetEvent (false );
Var transactionOptions1 = new TransactionOptions {IsolationLevel = IsolationLevel. ReadCommitted };
Var transactionOptions2 = new TransactionOptions {IsolationLevel = IsolationLevel. ReadUncommitted };
Using (var ts1 = new TransactionScope (transactionscospontion. Required, transactionOptions1 ))
{
// Add data
Using (var context = new TestEntities ())
{
Context. Tables. Add (new Table () {Id = Guid. NewGuid (), Name = "Duan Guangwei "});
Context. SaveChanges ();
}
ThreadPool. QueueUserWorkItem (data =>
{
Using (var ts2 = new TransactionScope (transactionscospontion. Required, transactionOptions2 ))
{
// Dirty read Test
Using (var context = new TestEntities ())
{
Assert. AreEqual (2, context. Tables. Count ());
}
}
AutoResetEvent. Set ();
});
AutoResetEvent. WaitOne ();
}
// Prerequisites
Using (var context = new TestEntities ())
{
Assert. AreEqual (1, context. Tables. Count ());
}
}
Non-repeated read
Definition: Transaction A reads data twice. During these two reads, transaction B modifies the data, the data read by transaction A is different (repeated read is not allowed ).
Metaphor: A obtained the source code twice during the source code review. During the two review processes, B modified the source code, B may modify the code reviewed by A, which may not comply with the specification.
Sample Code
Copy codeThe Code is as follows: [TestMethod]
Public void cannot be read repeatedly _ test ()
{
Var autoResetEvent = new AutoResetEvent (false );
Var transactionOptions1 = new TransactionOptions {IsolationLevel = IsolationLevel. ReadCommitted };
Var transactionOptions2 = new TransactionOptions {IsolationLevel = IsolationLevel. ReadCommitted };
Using (var ts1 = new TransactionScope (transactionscospontion. Required, transactionOptions1 ))
{
// Prerequisites
Using (var context = new TestEntities ())
{
Assert. AreEqual ("Li yunniu", context. Tables. First (). Name );
}
ThreadPool. QueueUserWorkItem (data =>
{
Using (var ts2 = new TransactionScope (transactionscospontion. Required, transactionOptions2 ))
{
// Modify data
Using (var context = new TestEntities ())
{
Context. Tables. First (). Name = "Duan Guangwei ";
Context. SaveChanges ();
}
Ts2.Complete ();
}
AutoResetEvent. Set ();
});
AutoResetEvent. WaitOne ();
// Non-repeated read Test
Using (var context = new TestEntities ())
{
Assert. AreEqual ("Duan Guangwei", context. Tables. First (). Name );
}
}
}
Phantom read
Definition: Transaction A reads the data twice. During the two reads, transaction B adds the data, and the set read by transaction A is different (phantom read ).
Metaphor: A adds A file to the statistical file during the two statistical processes in order to accurately calculate the data in the statistical file, A finds that the number of these two statistics is different (phantom read). A will feel A headache in his head.
Sample Code
Copy codeThe Code is as follows: [TestMethod]
Public void phantom read_test ()
{
Var autoResetEvent = new AutoResetEvent (false );
Var transactionOptions1 = new TransactionOptions {IsolationLevel = IsolationLevel. RepeatableRead };
Var transactionOptions2 = new TransactionOptions {IsolationLevel = IsolationLevel. ReadCommitted };
Using (var ts1 = new TransactionScope (transactionscospontion. Required, transactionOptions1 ))
{
// Prerequisites
Using (var context = new TestEntities ())
{
Assert. AreEqual (1, context. Tables. Count ());
}
ThreadPool. QueueUserWorkItem (data =>
{
Using (var ts2 = new TransactionScope (transactionscospontion. Required, transactionOptions2 ))
{
// Add data
Using (var context = new TestEntities ())
{
Context. Tables. Add (new Table () {Id = Guid. NewGuid (), Name = "Duan Guangwei "});
Context. SaveChanges ();
}
Ts2.Complete ();
}
AutoResetEvent. Set ();
});
AutoResetEvent. WaitOne ();
// Phantom read Test
Using (var context = new TestEntities ())
{
Assert. AreEqual (2, context. Tables. Count ());
}
}
}
How to handle concurrency issues at the four isolation levels
|
Dirty read |
Non-repeated read |
Phantom read |
Read not submitted |
Allow |
Allow |
Allow |
Read committed |
Not Allowed |
Allow |
Allow |
Repeatable read |
Not Allowed |
Not Allowed |
Allow |
Serializing |
Not Allowed |
Not Allowed |
Not Allowed |