MySQL 锁机制和事务(3)

可以通过–transaction-isolation参数设置实例级别的事务隔离级别,也可以通过set [session/global] transaction isolation 
level语句修改当前数据库链接或者是后续创建的所有数据库链接的事务隔离级别

1

2

3

4

5

6

7

 

SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL

{

READ UNCOMMITTED

| READ COMMITTED

| REPEATABLE READ

| SERIALIZABLE

}

 

REPEATABLE READ:可重复读,默认值。 表明对同一个事务来说第一次读数据时会创建快照,在事务结束前的其他读操作(不加锁)会获得和第一次读相同的结果。当读操作是加锁的读语句(select … for update或者lock in share mode),或者update和delete语句时,加锁的方式依赖于语句是否使用唯一索引访问唯一值或者范围值 

 当访问的是唯一索引的唯一值时,则InnoDB会在索引行施加行锁 
当访问唯一索引的范围值时,则会在扫描的索引行上增加间隔锁或者next-key锁以防止其他链接对此范围的插入

READ COMMITTED:读取提交内容。意味着每次读都会有自己最新的快照。对于加锁读语句(select … for update和lock in share mode),或者update, delete语句会在对应的行索引上增加锁,但不像可重复读一样会增加间隔锁,因此其他的事务执行插入操作时如果是插入非索引行上的数值,则不影响插入

由于该隔离级别是禁用间隔锁的,所以会导致幻读的情况 
如果是使用此隔离级别,就必须使用行级别的二进制日志 
此隔离级别还有另外的特点: 
对于update和delete语句只会在约束条件对应的行上增加锁 
对update语句来说,如果对应的行上已经有锁,则InnoDB会执行半一致读的操作,来确定update语句对应的行在上次commit之后的数据是否在锁的范围,如果不是,则不影响update操作,如果是,则需要等待对应的锁解开

例:

+ View Code?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

 

session1:

#设置为读提交

mysql> set session transaction isolation level read committed;

#关闭mysql默认的自动提交

mysql> set autocommit=0;

mysql> update temp set name='aaa' where >

mysql> select * from temp;

+----+------+

| id | name |

+----+------+

|  1 | aaa  |

|  2 | b    |

|  3 | c    |

|  4 | d    |

+----+------+

 

session2:

mysql> set session transaction isolation level read committed;

mysql> set autocommit=0;

mysql> select * from temp;

+----+------+

| id | name |

+----+------+

|  1 | a    |

|  2 | b    |

|  3 | c    |

|  4 | d    |

 

session1:

#提交session1的所有事务

commit;

 

session2:

mysql> select * from temp;

+----+------+

| id | name |

+----+------+

|  1 | aaa  |

|  2 | b    |

|  3 | c    |

|  4 | d    |

+----+------+

#同一个事务中能看到另一个事务已经提交的数据

mysql> commit;

 

比如如下情况

1

2

3

 

CREATE TABLE t (a INT NOT NULL, b INT) ENGINE = InnoDB;

INSERT INTO t VALUES (1,2),(2,3),(3,2),(4,3),(5,2);

COMMIT;

 

表中并没有任何索引,所以会使用隐藏创建的聚簇索引来施加行级锁 
当第一个链接执行修改:

1

2

3

4

5

6

 

当第一个SESSION链接执行修改:

SET autocommit = 0;

UPDATE t SET b = 5 WHERE b = 3;

之后第二个SESSION链接执行修改:

SET autocommit = 0;

UPDATE t SET b = 4 WHERE b = 2;

 

对可重复读隔离级别来说,第一个事务的修改会在每行记录上都增加排他锁,并且直到事务结束后锁才会释放

而第二个事务会一直等待前面事务的锁被释放后才能执行

READ UNCOMMITTED:读取未提交内容,所读到的数据可能是脏数据 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/6c657295ebb4837b7471e8c9aab82ec3.html