mysql 事务隔离
2015-11-04 00:00
766 查看
摘要: READ UNCOMMITTED 读未提交
READ COMMITTED 读提交
REPEATABLE 可重读
SERIALIABLE 可串读
Read uncommitted(读取未提交内容)
在该隔离级别,所有的事务都可以看到其他未提交的事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他的级别好多少。读取未提交的数据,也被称为脏读。
模拟实例: 需要两个终端
READ-COMMITTED (读取提交内容)
这是大多数数据库系统的默认系统隔离级别(但不是mysql默认的)。它满足了隔离的简单定义:事务的数据只有被提交才能被查询到。这种隔离级别也成为不可重复读,
以为同一事务的其他实例处理期间可能会有新的commit,所以同一个select会有不同的结果。
B终端:
Repeatable READ (可以重复读)
这是Mysql默认的事务隔离级别,它确保同一事务的多个实例在并发读数据时候,会看到同样的数据行。不过理论上,这会导致另一个问题(幻读)
(Phantom Read)简单的说,幻读是指永固读取某一个范围的数据行时,另一个事务又在该范围内插入了新行,当用户在读取该范围的
数据行是,会发现有新的幻影行,Innodb和falcon存储引擎通过多版本并发控制解决该问题 (MVCC,Multiversion Concurrency Control)机制
理解:A begin 读取的数据 和 B begin 读取的数据相同,如果B插入了数据,并commit ,A等待自己的事务完毕后才能重新读取B事务提交的数据。
Serializable(可串行化)
这种最高的隔离级别,它通过强制事务排序,使之不能相互冲突。从而解决幻读的问题。简而言之,它是在每个读的数据行上加上共享锁
在这个级别,可能导致大量的超时和锁竞争
READ COMMITTED 读提交
REPEATABLE 可重读
SERIALIABLE 可串读
Read uncommitted(读取未提交内容)
在该隔离级别,所有的事务都可以看到其他未提交的事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他的级别好多少。读取未提交的数据,也被称为脏读。
模拟实例: 需要两个终端
#注意,切换隔离级别建议退出mysql终端重新登录,否则有可能修改失败 A终端: #设置可以隔离模式 mysql> set global tx_isolation="READ-UNCOMMITTED"; Query OK, 0 rows affected (0.00 sec) mysql> select @@tx_isolation; +------------------+ | @@tx_isolation | +------------------+ | READ-UNCOMMITTED | +------------------+ 1 row in set (0.00 sec) mysql> use wangdk; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> desc user; +-------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | char(20) | NO | | | | +-------+------------------+------+-----+---------+----------------+ 2 rows in set (0.00 sec) mysql> select * from user; Empty set (0.00 sec) #开启事务 mysql> begin; Query OK, 0 rows affected (0.00 sec) #注意这里并未提交 commit mysql> insert into user(name) values("test"); Query OK, 1 row affected (0.00 sec) mysql> rollback; Query OK, 0 rows affected (0.00 sec)
B终端: mysql> set global tx_isolation="READ-UNCOMMITTED"; Query OK, 0 rows affected (0.00 sec) mysql> select @@tx_isolation; +------------------+ | @@tx_isolation | +------------------+ | READ-UNCOMMITTED | +------------------+ 1 row in set (0.00 sec) mysql> use wangdk; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed #注意:A终端并未 commit 提交事务。这里已经可以查到这个事务的数据,但是数据随时可以回滚的。 mysql> select * from user; +----+------+ | id | name | +----+------+ | 12 | test | +----+------+ 1 row in set (0.00 sec) #A终端 rollback 后数据消失 mysql> select * from user; Empty set (0.00 sec)
READ-COMMITTED (读取提交内容)
这是大多数数据库系统的默认系统隔离级别(但不是mysql默认的)。它满足了隔离的简单定义:事务的数据只有被提交才能被查询到。这种隔离级别也成为不可重复读,
以为同一事务的其他实例处理期间可能会有新的commit,所以同一个select会有不同的结果。
A终端: mysql> set global tx_isolation="READ-COMMITTED"; Query OK, 0 rows affected (0.00 sec) mysql> select @@tx_isolation; +----------------+ | @@tx_isolation | +----------------+ | READ-COMMITTED | +----------------+ 1 row in set (0.00 sec) mysql> use wangdk; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> select * from user; +----+------+ | id | name | +----+------+ | 13 | 1 | | 14 | 2 | | 15 | 4 | +----+------+ 3 rows in set (0.00 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) #删除一条数据,未提交事务 mysql> delete from user where id = 15; Query OK, 1 row affected (0.00 sec) #删除后A终端已经发生变化 mysql> select * from user; +----+------+ | id | name | +----+------+ | 13 | 1 | | 14 | 2 | +----+------+ 2 rows in set (0.00 sec)
B终端:
mysql> set global tx_isolation="READ-COMMITTED"; Query OK, 0 rows affected (0.00 sec) mysql> select @@tx_isolation; +----------------+ | @@tx_isolation | +----------------+ | READ-COMMITTED | +----------------+ 1 row in set (0.00 sec) mysql> use wangdk; Database changed mysql> select * from user; +----+------+ | id | name | +----+------+ | 13 | 1 | | 14 | 2 | | 15 | 4 | +----+------+ 3 rows in set (0.00 sec) #事务未提交B终端未发生变化 mysql> select * from user; +----+------+ | id | name | +----+------+ | 13 | 1 | | 14 | 2 | | 15 | 4 | +----+------+ 3 rows in set (0.00 sec)
Repeatable READ (可以重复读)
这是Mysql默认的事务隔离级别,它确保同一事务的多个实例在并发读数据时候,会看到同样的数据行。不过理论上,这会导致另一个问题(幻读)
(Phantom Read)简单的说,幻读是指永固读取某一个范围的数据行时,另一个事务又在该范围内插入了新行,当用户在读取该范围的
数据行是,会发现有新的幻影行,Innodb和falcon存储引擎通过多版本并发控制解决该问题 (MVCC,Multiversion Concurrency Control)机制
理解:A begin 读取的数据 和 B begin 读取的数据相同,如果B插入了数据,并commit ,A等待自己的事务完毕后才能重新读取B事务提交的数据。
模拟: A终端: mysql> select @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | +-----------------+ 1 row in set (0.00 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) B终端 mysql> select @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | +-----------------+ 1 row in set (0.00 sec) mysql> select * from user; +----+--------+ | id | name | +----+--------+ | 21 | wangdk | +----+--------+ 1 row in set (0.00 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> insert into user(name) values("hello"); Query OK, 1 row affected (0.01 sec) mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> select * from user; +----+--------+ | id | name | +----+--------+ | 21 | wangdk | | 22 | hello | +----+--------+ 2 rows in set (0.00 sec) A终端: #并未查找到B事务的数据 mysql> select * from user; +----+--------+ | id | name | +----+--------+ | 21 | wangdk | +----+--------+ 1 row in set (0.00 sec) mysql> commit; #必须等待A事务完成,才能读取到B事务已经提交上来的数据 mysql> select * from user; +----+--------+ | id | name | +----+--------+ | 21 | wangdk | | 22 | hello | +----+--------+ 3 rows in set (0.00 sec)
Serializable(可串行化)
这种最高的隔离级别,它通过强制事务排序,使之不能相互冲突。从而解决幻读的问题。简而言之,它是在每个读的数据行上加上共享锁
在这个级别,可能导致大量的超时和锁竞争
实例: A终端: mysql> select @@tx_isolation; +----------------+ | @@tx_isolation | +----------------+ | SERIALIZABLE | +----------------+ 1 row in set (0.00 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from wangdk.user; +----+--------+ | id | name | +----+--------+ | 21 | wangdk | | 22 | hello | | 23 | hello | +----+--------+ 3 rows in set (0.00 sec) #先不要提交,要先操作B终端,最后一句在执行commit mysql> commit; Query OK, 0 rows affected (0.00 sec) B 终端: mysql> select @@tx_isolation; +----------------+ | @@tx_isolation | +----------------+ | SERIALIZABLE | +----------------+ 1 row in set (0.01 sec) mysql> select * from wangdk.user; +----+--------+ | id | name | +----+--------+ | 21 | wangdk | | 22 | hello | | 23 | hello | +----+--------+ 3 rows in set (0.00 sec) #看到了么,更新秒数,等待A终端commit以后,这一句才会执行 mysql> update wangdk.user set name="wangdk1" where id = 21; Query OK, 1 row affected (17.09 sec) Rows matched: 1 Changed: 1 Warnings: 0
相关文章推荐
- MySQL中的integer 数据类型
- MySQL存储过程
- mysql中int、bigint、smallint 和 tinyint的区别与长度
- mysql load data 导出、导入 csv
- source命令执行SQL脚本文件
- MySQL创建用户及权限控制
- MySQL管理数据表
- linux下mysql添加用户
- mysql procedure
- mysql触发器
- MySQL 备份和恢复策略
- mac下安装mysql(转载)
- mysql 修改编码 Linux/Mac/Unix/通用(杜绝修改后无法启动的情况!)
- MySQL数据的导出、导入(mysql内部命令:mysqldump、mysql)
- mysql数据行转列
- Linux下修改MySQL编码的方法
- MySQL Server 日志
- MySQL 安全事宜
- MySQL 备份与恢复