It is tested with Mysql 5.5.
Some of the information are taken from http://dev.mysql.com/doc/refman/5.5/en/innodb-transaction-model.html.
1. BACKGROUND
1. Mysql InnoDB does locking on row level.
* Record lock: This is a lock on an index record. Record locks always lock index records, even if a table is defined with no indexes. For such cases, InnoDB creates a hidden clustered index and uses this index for record locking
* Gap lock: This is a lock on a gap between index records, or a lock on the gap before the first or after the last index record.
* Next-key lock: This is a combination of a record lock on the index record and a gap lock on the gap before the index record.
2. Mysql supports following transaction isolation levels
i. REPEATABLE READ
Features:
* Dirty Read => NO: It does not read uncommitted results.
* Repeatable read => YES: In a transaction, multiple select statements return same row with same content
* Phantom read => YES: In a transaction, multiple select statements return same result set with exact same number
* For UPDATE, and DELETE statements, locking depends on whether the statement uses a unique index with a unique search condition, or a range-type search condition. For a unique index with a unique search condition, InnoDB locks only the index record found, not the gap before it. For other search conditions, InnoDB locks the index range scanned, using gap locks or next-key (gap plus index-record) locks to block insertions by other sessions into the gaps covered by the range.
ii. READ COMMITTED
* Dirty Read: NO : It does not read uncommitted results.
* Repeatable read => NO : Each consistent read, even within the same transaction, sets and reads its own fresh snapshot. This means that multiple select statements may return different content for the same row.
* Phantom Read => YES
* For UPDATE statements, and DELETE statements, InnoDB locks only index records, not the gaps before them, and thus permits the free insertion of new records next to locked records.
iii. READ UNCOMMITTED
iv. SERIALIZABLE
3. In InnoDB, all user activity occurs inside a transaction. If auto-commit mode is enabled, each SQL statement forms a single transaction on its own.
4. By default, MySQL starts the session for each new connection with auto-commit enabled, so MySQL does a commit after each SQL statement if that statement did not return an error.
5. If auto-commit mode is disabled within a session with SET auto-commit = 0, the session always has a transaction open. A COMMIT or ROLLBACK statement ends the current transaction and a new one starts.
We will investigate two scenarios.
* Two transactions making UPDATE on same table
* One transaction making INSERT after another transaction making UPDATE on same table
* For UPDATE, and DELETE statements, locking depends on whether the statement uses a unique index with a unique search condition, or a range-type search condition. For a unique index with a unique search condition, InnoDB locks only the index record found, not the gap before it. For other search conditions, InnoDB locks the index range scanned, using gap locks or next-key (gap plus index-record) locks to block insertions by other sessions into the gaps covered by the range.
ii. READ COMMITTED
* Dirty Read: NO : It does not read uncommitted results.
* Repeatable read => NO : Each consistent read, even within the same transaction, sets and reads its own fresh snapshot. This means that multiple select statements may return different content for the same row.
* Phantom Read => YES
* For UPDATE statements, and DELETE statements, InnoDB locks only index records, not the gaps before them, and thus permits the free insertion of new records next to locked records.
iii. READ UNCOMMITTED
iv. SERIALIZABLE
3. In InnoDB, all user activity occurs inside a transaction. If auto-commit mode is enabled, each SQL statement forms a single transaction on its own.
4. By default, MySQL starts the session for each new connection with auto-commit enabled, so MySQL does a commit after each SQL statement if that statement did not return an error.
5. If auto-commit mode is disabled within a session with SET auto-commit = 0, the session always has a transaction open. A COMMIT or ROLLBACK statement ends the current transaction and a new one starts.
2. SETUP
* Two transactions making UPDATE on same table
* One transaction making INSERT after another transaction making UPDATE on same table
We will try each scenario for each of above tables
mytable
-id (Primary Key)
-name (Secondary Index)
-value
mytable_no_index
-id (Primary Key)
-name
-value
-id (Primary Key)
-name (Secondary Index)
-value
mytable_no_index
-id (Primary Key)
-name
-value
3. SCENARIO 1 - Two transactions making UPDATE
CASE 1 - Table without secondary index - mytable_no_index
i. REPEATABLE_READ
Transaction 1
|
Transaction 2
|
Start Transaction
|
Start Transaction
|
UPDATE mytable_no_index SET value=22 WHERE name='a'
|
...
|
Get lock and run query
|
UPDATE mytable_no_index SET value=22 WHERE name='b'
|
...
|
Blocked waiting for lock
|
...
|
Blocked waiting for lock
|
Commit Transaction
|
Get lock and run query
|
Commit Transaction
|
ii. READ_COMMITED
SCENARIO 1 Transaction 1
|
Transaction 2
|
Start Transaction
|
Start Transaction
|
UPDATE mytable_no_index SET value=22 WHERE name='a'
|
...
|
Get lock and run query
|
UPDATE mytable_no_index SET value=22 WHERE name='b'
|
...
|
Get lock and run query
|
...
|
...
|
Commit Transaction
|
...
|
Commit Transaction
|
CASE 2 - Table with secondary index - mytable
i. REPEATABLE_READ
Transaction 1
|
Transaction 2
|
Start Transaction
|
Start Transaction
|
UPDATE mytable SET value=22 WHERE name='a'
|
...
|
Get lock and run query
|
UPDATE mytable SET value=22 WHERE name='b'
|
...
|
Get lock and run query
|
...
|
...
|
Commit Transaction
|
...
|
Commit Transaction
|
Lets expand it more:
Transaction 1
|
Transaction 2
|
Start Transaction
|
Start Transaction
|
UPDATE mytable SET value=22 WHERE name='a' and value=1
|
...
|
Get lock and run query
|
UPDATE mytable SET value=22 WHERE name='a' and value=2
|
...
|
Blocked waiting for lock
|
...
|
Blocked waiting for lock
|
Commit Transaction
|
Get lock and run query
|
Commit Transaction
|
ii. READ_COMMITED
Transaction 1
|
Transaction 2
|
Start Transaction
|
Start Transaction
|
UPDATE mytable SET value=22 WHERE name='a'
|
...
|
Get lock and run query
|
UPDATE mytable SET value=22 WHERE name='b'
|
...
|
Get lock and run query
|
...
|
...
|
Commit Transaction
|
...
|
Commit Transaction
|
4. SCENARIO 2 - One transaction making INSERT after another transaction making UPDATE
CASE 1 - Table without secondary index - mytable_no_index
i. REPEATABLE_READ
Transaction 1
|
Transaction 2
|
Start Transaction
|
Start Transaction
|
UPDATE mytable_no_index SET value=22 WHERE name='a'
|
...
|
Get lock and run query
|
INSERT INTO mytable_no_index(name, value) VALUES(‘abc’, 1)
|
...
|
Blocked waiting for lock
|
...
|
Blocked waiting for lock
|
Commit Transaction
|
Get lock and run query
|
Commit Transaction
|
ii. READ_COMMITED
Transaction 1
|
Transaction 2
|
Start Transaction
|
Start Transaction
|
UPDATE mytable_no_index SET value=22 WHERE name='a'
|
...
|
Get lock and run query
|
INSERT INTO mytable_no_index(name, value) VALUES(‘abc’, 1)
|
...
|
Get lock and run query
|
...
|
...
|
Commit Transaction
|
...
|
Commit Transaction
|
CASE 2 - Table with secondary index - mytable
i. REPEATABLE_READ
Transaction 1
|
Transaction 2
|
Start Transaction
|
Start Transaction
|
UPDATE mytable SET value=22 WHERE name='a'
|
...
|
Get lock and run query
|
INSERT INTO mytable(name, value) VALUES(‘abc’, 1)
|
...
|
Blocked waiting for lock
|
...
|
Blocked waiting for lock
|
Commit Transaction
|
Get lock and run query
|
Commit Transaction
|
Lets expand more.
Transaction 1
|
Transaction 2
|
Start Transaction
|
Start Transaction
|
UPDATE mytable SET value=22 WHERE name='a'
|
...
|
Get lock and run query
|
INSERT INTO mytable(name, value) VALUES(‘bcd’, 1)
|
...
|
Get lock and run query
|
...
|
...
|
Commit Transaction
|
...
|
Commit Transaction
|
Since bcd is after index record a, it will not wait for lock
Transaction 1
|
Transaction 2
|
Start Transaction
|
Start Transaction
|
UPDATE mytable SET value=22 WHERE name='a'
|
...
|
Get lock and run query
|
INSERT INTO mytable(name, value) VALUES(‘012’, 1)
|
...
|
Blocked waiting for lock
|
...
|
Blocked waiting for lock
|
Commit Transaction
|
Get lock and run query
|
Commit Transaction
|
ii. READ_COMMITED
Transaction 1
|
Transaction 2
|
Start Transaction
|
Start Transaction
|
UPDATE mytable SET value=22 WHERE name='a'
|
...
|
Get lock and run query
|
INSERT INTO mytable(name, value) VALUES(‘abc’, 1)
|
...
|
Get lock and run query
|
...
|
...
|
Commit Transaction
|
...
|
Commit Transaction
|
5. DISABLING GAP LOCKS
Excerpt from MySQL documentation
Gap locking can be disabled explicitly. This occurs if you change the transaction isolation level to READ_COMMITTED or enable the innodb_locks_unsafe_for_binlog system variable. Under these circumstances, gap locking is disabled for searches and index scans and is used only for foreign-key constraint checking and duplicate-key checking.
If innodb_locks_unsafe_for_binlog variable is set to false, insert operations will not be blocked.
6. Where to Go From Here
http://dev.mysql.com/doc/refman/5.5/en/set-transaction.html
I have to voice my passion for your kindness giving support to those people that should have guidance on this important matter.
YanıtlaSilBest PHP Training Institute in Chennai|PHP Course in chennai
Best .Net Training Institute in Chennai
MCSE Training in Chennai
AI Training in Chennai
SEO Training in Chennai