ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

015、事务的实验

2021-06-22 15:35:02  阅读:205  来源: 互联网

标签:事务 rows read 0.00 sec 015 mysql 实验


事务的隔离级别

事务的隔离级别:read uncommitted,RU,读未提交。一个事务中,可以读取到其他事务未提交的变更。该级别属于脏读。read committed,RC,读已提交。一个事务中,可以读取到其他事务已经提交的变更。该级别允许幻读,不可重复读的发生。repetable read,RR,可重复读。一个事务中,直到事务结束前,都可以反复读取到事务一开始看到底数据,不会发生变化。该级别可保证事务一致性。serializable,SR,串行。即每次读都需要获得表级共享锁,每次写都加表级排它锁,两个会话间读写会相互阻塞。该级别会导致innodb表的并发特性丧失,变成myisam一样。
如果没有事务控制的话,那么并发读写数据库会有什么隐患?脏读:一个事务按相同的查询条件重新读取以前检索过的数据,发现其他事务更新后达到了满足其查询条件的旧数据(此时它还未被提交),这种现象就称为“脏读”。简单讲就是一个会话读取到了另一个会话还未提交的事务。这种现象一定要避免发生,涉及到的事务隔离级别为RU。不可重复读:一个事务按相同的查询条件重新读取以前检索过的数据,发现其他事务更新后达到了满足其查询条件的旧数据(此时它已被提交),这种现象称为“不可重复读”。幻读:一个事务按相同的查询条件重新读取以前检索过的数据,发现其他事务插入了满足其查询条件的新数据(此时它已被提交),这种现象就称为“幻读”。

修改事务隔离级别

需要执行两条命令:
mysql> show variables like '%iso%';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)

mysql> set global transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)
--隔离级别可以为:read uncommitted;read committed;repeatable read;serializable;
mysql> set session transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)
确认结果:
mysql> show variables like '%iso%';
+---------------+------------------+
| Variable_name | Value            |
+---------------+------------------+
| tx_isolation  | READ-UNCOMMITTED |
+---------------+------------------+
1 row in set (0.00 sec)

脏读

在讲之前,先了解脏页的概念。脏页:指的是在缓冲池中已经被修改的页,但是还没有刷新到磁盘,即数据库实例内存中的页和磁盘中的页数据是不一致的。当然在刷新到磁盘之前,日志已经被写入到日志文件中。而所谓的脏数据,是在缓冲池中被修改的数据,并且还没有被提交的。对于脏页的读取,是非常正常的,脏页是因为数据库实例和磁盘的异步同步造成的,这并不影响数据的一致性,并且因为是异步的,因此可以带来性能的提高。而脏数据却不同,脏数据是指未提交的数据,如果读到了脏数据,即一个事务可以读到另一个事务未提交的数据,这显然违反了数据库的隔离性。读未提交(RU)隔离级别会出现脏读现象,示例:
修改数据库的事务隔离级别:
mysql> set global transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)

mysql> set session transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%iso%';
+---------------+------------------+
| Variable_name | Value            |
+---------------+------------------+
| tx_isolation  | READ-UNCOMMITTED |
+---------------+------------------+
1 row in set (0.00 sec)
会话1开启事务,插入数据,先不提交:
mysql> use test;
Database changed
mysql> select * from t;
+------+------+
| id   | name |
+------+------+
|    1 | aa   |
|    2 | b    |
|    3 | c    |
|    4 | d    |
+------+------+
4 rows in set (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t values(1,'read-uncommited');
Query OK, 1 row affected (0.00 sec)
会话2连接到数据库,查看表t的数据,可以查询到未提交的数据:
mysql> use test;
Database changed
mysql> select * from t;
+------+-----------------+
| id   | name            |
+------+-----------------+
|    1 | aa              |
|    2 | b               |
|    3 | c               |
|    4 | d               |
|    1 | read-uncommited |
+------+-----------------+
5 rows in set (0.00 sec)
脏读在生产环境是不允许出现的情况,所以一般情况下,事务隔离级别不选择RU。

不可重复读

不可重复读:一个事务按相同的查询条件重新读取以前检索过的数据,发现其他事务更新后达到了满足其查询条件的旧数据(此时它已被提交),这种现象称为“不可重复读”。详细解释:在一个事务内多次读同一数据,在这个事务还没有结束时,另外一个事务也访问该同一数据。那么在第一个事务的两次读数据之间,由于第二个事务的修改,第一个事务两次读到的数据可能是不一样的,这样就发生了一个事务内两次读到的数据是不一样的,因此称为不可重复读。不可重复读和脏读的区别:脏读是读到未提交的数据,而不可重复读是读取到已经提交的数据,但是违反了数据库事务一致性的要求。在读已提交(RC)隔离级别,会出现不可重复读和幻读现象,对于事务一致性要求不高的,互联网类的公司,可以使用。
实验,修改事务隔离级别:
mysql> set global transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)

mysql> set session transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%iso%';
+---------------+----------------+
| Variable_name | Value          |
+---------------+----------------+
| tx_isolation  | READ-COMMITTED |
+---------------+----------------+
1 row in set (0.00 sec)
会话1开启事务,并执行更新操作:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> update t set name='read-commited' where id=1;
Query OK, 2 rows affected (0.07 sec)
Rows matched: 2  Changed: 2  Warnings: 0
会话2开启事务,查询表t:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t;
+------+-----------------+
| id   | name            |
+------+-----------------+
|    1 | aa              |
|    2 | b               |
|    3 | c               |
|    4 | d               |
|    1 | read-uncommited |
+------+-----------------+
5 rows in set (0.00 sec)
并没有查看到更新数据,此时将会话1进行提交,会话2再次查询:
mysql> commit;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from t;
+------+---------------+
| id   | name          |
+------+---------------+
|    1 | read-commited |
|    2 | b             |
|    3 | c             |
|    4 | d             |
|    1 | read-commited |
+------+---------------+
5 rows in set (0.00 sec)
结果数据提交后可以查看到提交之后的数据。总结:不可重复读的问题是可以接受的,因为读到的是已经提交的数据,本身不会带来很大的问题。因此很多数据库厂商(oracle、MSS)将其数据库事务隔离级别默认设置为read committed,这种隔离级别下允许不可重复读的现象。
innodb存储引擎中,通过使用next-key lock算法来避免不可重复度的问题,在mysql官方文档中,将不可重复读定义为幻象问题。innodb默认的存储引擎的默认事务隔离级别是read repeatable,采用next-key lock算法,就避免了不可重复读现象。

幻读

幻读:一个事务按相同的查询条件重新读取以前检索过的数据,发现其他事务插入了满足其查询条件的新数据(此时它已被提交),这种现象就称为“幻读”。幻读概念(另外一个session读取到了新增数据的信息)。在RC隔离级别下,会话1开启事务,并新增数据:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t values(5,'huandu');
Query OK, 1 row affected (0.00 sec)
会话2查询表t:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t;
+------+---------------+
| id   | name          |
+------+---------------+
|    1 | read-commited |
|    2 | b             |
|    3 | c             |
|    4 | d             |
|    1 | read-commited |
+------+---------------+
5 rows in set (0.00 sec)
会话1提交,会话2查询表t数据:
mysql> commit;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from t;
+------+---------------+
| id   | name          |
+------+---------------+
|    1 | read-commited |
|    2 | b             |
|    3 | c             |
|    4 | d             |
|    1 | read-commited |
|    5 | huandu        |
+------+---------------+
6 rows in set (0.00 sec)
查询到了新增并且提交的数据。这就是幻读。

可重复读

MySQL默认的隔离级别,不允许出现幻读,脏读,不可重复读现象。在线交易类的系统,支付,很多都使用RR这个隔离级别。修改MySQL隔离级别为RR:
mysql> set global transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)

mysql> set session transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%iso%';
+---------------+-----------------+
| Variable_name | Value           |
+---------------+-----------------+
| tx_isolation  | REPEATABLE-READ |
+---------------+-----------------+
1 row in set (0.00 sec)
会话1开启事务,并插入数据:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t values(6,'RR');
Query OK, 1 row affected (0.00 sec)
会话2开启事务,并查询数据:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t;
+------+---------------+
| id   | name          |
+------+---------------+
|    1 | read-commited |
|    2 | b             |
|    3 | c             |
|    4 | d             |
|    1 | read-commited |
|    5 | huandu        |
+------+---------------+
会话1提交事务,会话2查询数据:
mysql> commit;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from t;
+------+---------------+
| id   | name          |
+------+---------------+
|    1 | read-commited |
|    2 | b             |
|    3 | c             |
|    4 | d             |
|    1 | read-commited |
|    5 | huandu        |
+------+---------------+
6 rows in set (0.00 sec)
会话1提交以后,会话2没有查询到新增的数据,读取的数据还是原来的数据,这种现象称为可重复读。如果在会话2查看最新的数据,需要加for update选项:
mysql> select * from t for update;
+------+---------------+
| id   | name          |
+------+---------------+
|    1 | read-commited |
|    2 | b             |
|    3 | c             |
|    4 | d             |
|    1 | read-commited |
|    5 | huandu        |
|    6 | RR            |
+------+---------------+
7 rows in set (0.00 sec)
---如果不加for update,还是查看的原来的数据
mysql> select * from t;
+------+---------------+
| id   | name          |
+------+---------------+
|    1 | read-commited |
|    2 | b             |
|    3 | c             |
|    4 | d             |
|    1 | read-commited |
|    5 | huandu        |
+------+---------------+
6 rows in set (0.00 sec)
串行读,serializable,SR,串行。即每次读都需要获得表级共享锁,每次写都加表级排它锁,两个会话间读写会相互阻塞。该级别会导致innodb表的并发特性丧失,变成myisam一样。所以基本上不使用这种事务隔离级别。

来自为知笔记(Wiz)

标签:事务,rows,read,0.00,sec,015,mysql,实验
来源: https://www.cnblogs.com/youdiancaidaren/p/14918785.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有