标签:
原文 http://blog.csdn.net/xifeijian/article/details/20313977
读数据一致性及允许的并发副作用
隔离级别
|
读数据一致性
|
脏读
|
不可重复读
|
幻读
|
未提交读(Read uncommitted)
|
最低级别,只能保证不读取物理上损坏的数据
|
是
|
是
|
是
|
已提交度(Read committed)
|
语句级
|
否
|
是
|
是
|
可重复读(Repeatable read)
|
事务级
|
否
|
否
|
是
|
可序列化(Serializable)
|
最高级别,事务级
|
否
|
否
|
否
|
请求锁模式
是否兼容
当前锁模式
|
X
|
IX
|
S
|
IS
|
X
|
冲突
|
冲突
|
冲突
|
冲突
|
IX
|
冲突
|
兼容
|
冲突
|
兼容
|
S
|
冲突
|
冲突
|
兼容
|
兼容
|
IS
|
冲突
|
兼容
|
兼容
|
兼容
|
session_1
|
session_2
|
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
|
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
|
mysql> select * from tab_with_index where id = 1 and name = ‘1‘ for update;
+------+------+
| id | name |
+------+------+
| 1 | 1 |
+------+------+
1 row in set (0.00 sec)
|
|
虽然session_2访问的是和session_1不同的记录,但是因为使用了相同的索引,所以需要等待锁:
mysql> select * from tab_with_index where id = 1 and name = ‘4‘ for update;
等待
|
session_1
|
session_2
|
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
|
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)
|
mysql> select * from tab_with_index where id = 1 for update;
+------+------+
| id | name |
+------+------+
| 1 | 1 |
| 1 | 4 |
+------+------+
2 rows in set (0.00 sec)
|
|
Session_2使用name的索引访问记录,因为记录没有被索引,所以可以获得锁:
mysql> select * from tab_with_index where name = ‘2‘ for update;
+------+------+
| id | name |
+------+------+
| 2 | 2 |
+------+------+
1 row in set (0.00 sec)
|
|
由于访问的记录已经被session_1锁定,所以等待获得锁。:
mysql> select * from tab_with_index where name = ‘4‘ for update;
|
session_1
|
session_2
|
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
|
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
|
当前session对不存在的记录加for update的锁:
mysql> select * from emp where empid = 102 for update;
Empty set (0.00 sec)
|
|
这时,如果其他session插入empid为102的记录(注意:这条记录并不存在),也会出现锁等待:
mysql>insert into emp(empid,...) values(102,...);
阻塞等待
|
|
Session_1 执行rollback:
mysql> rollback;
Query OK, 0 rows affected (13.04 sec)
|
|
由于其他session_1回退后释放了Next-Key锁,当前session可以获得锁并成功插入记录:
mysql>insert into emp(empid,...) values(102,...);
Query OK, 1 row affected (13.35 sec)
|
另 外,对于“insert into target_tab select * from source_tab where ...”和“create table new_tab ...select ... From source_tab where ...(CTAS)”这种SQL语句,用户并没有对source_tab做任何更新操作,但MySQL对这种SQL语句做了特别处理。
隔离级别
一致性读和锁
SQL
|
Read Uncommited
|
Read Commited
|
Repeatable Read
|
Serializable
|
|
SQL
|
条件
|
||||
select
|
相等
|
None locks
|
Consisten read/None lock
|
Consisten read/None lock
|
Share locks
|
范围
|
None locks
|
Consisten read/None lock
|
Consisten read/None lock
|
Share Next-Key
|
|
update
|
相等
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
Exclusive locks
|
范围
|
exclusive next-key
|
exclusive next-key
|
exclusive next-key
|
exclusive next-key
|
|
Insert
|
N/A
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
replace
|
无键冲突
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
键冲突
|
exclusive next-key
|
exclusive next-key
|
exclusive next-key
|
exclusive next-key
|
|
delete
|
相等
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
范围
|
exclusive next-key
|
exclusive next-key
|
exclusive next-key
|
exclusive next-key
|
|
Select ... from ... Lock in share mode
|
相等
|
Share locks
|
Share locks
|
Share locks
|
Share locks
|
范围
|
Share locks
|
Share locks
|
Share Next-Key
|
Share Next-Key
|
|
Select * from ... For update
|
相等
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
exclusive locks
|
范围
|
exclusive locks
|
Share locks
|
exclusive next-key
|
exclusive next-key
|
|
Insert into ... Select ...
(指源表锁)
|
innodb_locks_unsafe_for_binlog=off
|
Share Next-Key
|
Share Next-Key
|
Share Next-Key
|
Share Next-Key
|
innodb_locks_unsafe_for_binlog=on
|
None locks
|
Consisten read/None lock
|
Consisten read/None lock
|
Share Next-Key
|
|
create table ... Select ...
(指源表锁)
|
innodb_locks_unsafe_for_binlog=off
|
Share Next-Key
|
Share Next-Key
|
Share Next-Key
|
Share Next-Key
|
innodb_locks_unsafe_for_binlog=on
|
None locks
|
Consisten read/None lock
|
Consisten read/None lock
|
Share Next-Key
|
session_1
|
session_2
|
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from table_1 where where id=1 for update;
...
做一些其他处理...
|
mysql> set autocommit = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from table_2 where id=1 for update;
...
|
select * from table_2 where id =1 for update;
因session_2已取得排他锁,等待
|
做一些其他处理...
|
mysql> select * from table_1 where where id=1 for update;
死锁
|
标签:
原文地址:http://www.cnblogs.com/ly7454/p/4799930.html