1、数据库事务基本特征
1.原子性
2.一致性
3.隔离性
4.持久性
2、第一类丢失更新
假设要更新一个计数器count=10,事务1将count+1(即update count=11),事务2也将count+1,当事务1提交 成功,事务2提交成功,事务2失败回滚,回滚到最初态count=10,事务1的更新将被丢失
3、第二类丢失更新
假设要更新一个计数器count(10),事务1将count+1,事务2也将count+1,那么两个事务提交后,count更新为11和意想的12不一致
注意:设置隔离等级并不能解决第二类更新丢失,隔离等级决定的是事务查询更新处于怎么样的环境,无论隔离等级如何,
第二类更新丢失总是存在,因为它是以后者覆盖前者,和隔离时的可见性没有必然联系。MySQL的update是互斥的,即一个在update(可能是事务),另一update必须阻塞直到其他update完成(事务提交),这样一来,无论隔离等级如何,使用count=count+1这种方式更新是不会出现第二类更新
二、隔离等级
1、查询当前隔离等级
Select @@tx_isolation/@@transaction_isolation;
2、设置当前会话隔离等级
Set session transaction isolation level isolation_level(read uncommitted, read committed, repeatable read, serializable;
3、read uncommitted读未提交
在一次事务中,若其他事务产生了更新或插入(尽管未提交),该事务查询可见更新或插入
1、在进行数据库操作的两个事务,事务1( READ-COMMITTED)进行update操作,事务2(READ-UNCOMMITTED)进行查询操作(事务1提交前),事务2能成功查询到事务1的未提交更新
事务1:

1 mysql> select @@tx_isolation; 2 3 +---------------------------+ 4 5 | @@tx_isolation | 6 7 +---------------------------+ 8 9 | READ-COMMITTED | 10 11 +---------------------------+ 12 13 1 row in set (0.00 sec) 14 15 16 17 mysql> begin; 18 19 Query OK, 0 rows affected (0.00 sec) 20 21 mysql> select * from user; 22 23 +----+-----------+-----+ 24 25 | id | user_name | sex | 26 27 +----+-----------+-----+ 28 29 | 1 | jyin | 1 | 30 31 | 2 | mike | 1 | 32 33 | 3 | john | 1 | 34 35 +----+-----------+-----+ 36 37 3 rows in set (0.00 sec) 38 39 mysql> update user set sex=2 where id=3; 40 41 Query OK, 1 row affected (0.01 sec)
事务2:

1 mysql> select @@tx_isolation; 2 3 +------------------+ 4 5 | @@tx_isolation | 6 7 +------------------+ 8 9 | READ-UNCOMMITTED | 10 11 +------------------+ 12 13 1 row in set (0.00 sec) 14 15 16 17 mysql> begin; 18 19 Query OK, 0 rows affected (0.00 sec) 20 21 mysql> select * from user; 22 23 +----+-----------+-----+ 24 25 | id | user_name | sex | 26 27 +----+-----------+-----+ 28 29 | 1 | jyin | 1 | 30 31 | 2 | mike | 1 | 32 33 | 3 | john | 2 | 34 35 +----+-----------+-----+
2、反之,事务1无法查询到事务2的未提交更新
事务1(事务2进行update操作后)

1 mysql> begin; 2 3 Query OK, 0 rows affected (0.00 sec) 4 5 mysql> select * from user; 6 7 +----+-----------+-----+ 8 9 | id | user_name | sex | 10 11 +----+-----------+-----+ 12 13 | 1 | jyin | 1 | 14 15 | 2 | mike | 1 | 16 17 | 3 | john | 1 | 18 19 +----+-----------+-----+ 20 21 3 rows in set (0.00 sec)
事务2

1 mysql> begin; 2 3 Query OK, 0 rows affected (0.00 sec) 4 5 mysql> update user set sex=2; 6 7 Query OK, 3 rows affected (0.02 sec) 8 9 Rows matched: 3 Changed: 3 Warnings: 0
4、read committed读已提交
在一次事务中,若其他事务产生了更新插入提交,该事务查询可见提交
5、repeatable read可重读
在一次事务中,第一次查询和第二次查询结果一致(中间无主动更新或插入),对其他事务更新插入提交不可见
事务1

1 mysql> begin; 2 3 Query OK, 0 rows affected (0.00 sec) 4 5 mysql> select * from user; 6 7 +----+-----------+-----+ 8 9 | id | user_name | sex | 10 11 +----+-----------+-----+ 12 13 | 1 | jyin | 1 | 14 15 | 2 | mike | 1 | 16 17 | 3 | john | 2 | 18 19 +----+-----------+-----+ 20 21 3 rows in set (0.01 sec) 22 23 24 25 mysql> update user set sex=1 where id=3; 26 27 Query OK, 1 row affected (0.01 sec) 28 29 Rows matched: 1 Changed: 1 Warnings: 0
在事务1提交前进行事务2(repeatable read)

1 mysql> begin; 2 3 Query OK, 0 rows affected (0.00 sec) 4 5 mysql> select * from user; 6 7 +----+-----------+-----+ 8 9 | id | user_name | sex | 10 11 +----+-----------+-----+ 12 13 | 1 | jyin | 1 | 14 15 | 2 | mike | 1 | 16 17 | 3 | john | 2 | 18 19 +----+-----------+-----+ 20 21 3 rows in set (0.00 sec)
然后事务1提交,事务2再次进行查询

1 mysql> select * from user; 2 3 +----+-----------+-----+ 4 5 | id | user_name | sex | 6 7 +----+-----------+-----+ 8 9 | 1 | jyin | 1 | 10 11 | 2 | mike | 1 | 12 13 | 3 | john | 2 | 14 15 +----+-----------+-----+ 16 17 3 rows in set (0.00 sec) 18 19 20 21 mysql> commit; 22 23 Query OK, 0 rows affected (0.00 sec) 24 25 26 27 mysql> select * from user; 28 29 +----+-----------+-----+ 30 31 | id | user_name | sex | 32 33 +----+-----------+-----+ 34 35 | 1 | jyin | 1 | 36 37 | 2 | mike | 1 | 38 39 | 3 | john | 1 | 40 41 +----+-----------+-----+ 42 43 3 rows in set (0.00 sec)
6、serializable
在一次事务中,在进行更新或插入操作时,其他事务开始更新或插入,该事务将被阻塞,直到其他事务被提交
事务1

1 mysql> begin; 2 3 Query OK, 0 rows affected (0.00 sec) 4 5 mysql> insert user(user_name, sex) values('cherry', 2); 6 7 Query OK, 1 row affected (0.01 sec)
在提交前进行事务2

1 mysql> select @@tx_isolation; 2 3 +----------------+ 4 5 | @@tx_isolation | 6 7 +----------------+ 8 9 | SERIALIZABLE | 10 11 +----------------+ 12 13 1 row in set (0.00 sec) 14 15 16 17 mysql> begin; 18 19 Query OK, 0 rows affected (0.00 sec) 20 21 mysql> select * from user;(在此阻塞直到事务1提交才能完成查询) 22 23 +----+-----------+-----+ 24 25 | id | user_name | sex | 26 27 +----+-----------+-----+ 28 29 | 1 | jyin | 1 | 30 31 | 2 | mike | 1 | 32 33 | 3 | john | 1 | 34 35 | 4 | cherry | 2 | 36 37 +----+-----------+-----+ 38 39 4 rows in set (11.78 sec)
如果事务2在事务1进行插入或更新操作前进行查询,然后事务1进行插入或更新,事务1会被阻塞直到事务2提交
6、隔离等级和可能发生的现象
|
脏读 |
不可重复读 |
幻读 |
未提交读 |
√ |
√ |
√ |
读写提交 |
× |
√ |
√ |
可重复读 |
× |
× |
√ |
串行化 |
× |
× |
× |