数据库事务

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)
View Code

事务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 +----+-----------+-----+
View Code

    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)
View Code 

事务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
View Code 

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
View Code 

在事务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)
View Code

然后事务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)
View Code

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)
View Code 

在提交前进行事务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)
View Code

如果事务2在事务1进行插入或更新操作前进行查询,然后事务1进行插入或更新,事务1会被阻塞直到事务2提交

6、隔离等级和可能发生的现象

 

脏读

不可重复读

幻读

未提交读

读写提交

×

可重复读

×

×

串行化

×

×

×

posted @ 2019-09-04 16:30  Atua  阅读(152)  评论(0编辑  收藏  举报