MySQL的事务处理以及隔离级别

来源:互联网 发布:java jxl.jar 64位 编辑:程序博客网 时间:2024/05/16 12:21

事务是DBMS的执行单位。它由有限的数据库操作序列组成的。但不是任意的数据库操作序列都能成为事务。一般来说,事物必须满足4个条件(ACID)

  • 原子性(Autmic):事务在执行时,要做到“要么不做,要么全做“,就是说不允许事务部分的执行。即使因为故障而使事务不能完成,在rollback时也要消除对数据库的影响!
  • 一致性(Consistency):事务操作之后,数据库所处的状态和业务规则是一致的。比如a, b账户相互转账之后,总金额不变。
  • 隔离性(Isolation):如果多个事务并发执行,应像各个事务独立执行一样
  • 持久性(Durability):事务提交后被持久化到数据库。

MySQL的事务处理方法

  1. 用BEGIN, ROLLBACK, COMMIT来实现
    开始:start transaction或者begin语句可以开始一项新的事务
    提交:commit可以提交当前事务,使变更成为永久变更
    回滚:rollback可以回滚当前事务,取消其变更
  2. 直接用set来改变mysql的自动提交模式
    MySQL默认是自动提交的,也就是你提交一个query,它就直接执行。我们可以通过set autocommit=0 禁止自动提交。set autocommit=1 开启自动提交来实现事务的处理。但注意当你用 set autocommit=0 的时候,你以后所有的SQL都将作为事务处理,直到你用commit确认或者rollback结束,并且只用于当前连接。MySQL中只有InnoDB和BDB类型的数据表才能支持事务处理。其他的类型是不支持的!

脏读,不可重复读,幻读

  • 脏读:一个事务读取了另一个未提交的并行事务写的数据。事务T1更新了一行记录的内容,但是并没有提交所做的更改。事务T2读取更新后的行,然后T1执行回滚操作,取消了刚才所做的修改。现在T2所读取的行就无效了(大部分数据库缺省的事务隔离级别都不会出现这种状态)
  • 不可重复读:一个事务重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务修改过。事务T1读取一行记录。紧接着事务T2修改了T1刚才读取的那一行记录。然后T1又再次读取这行记录,发现与刚才读取的结果不同。这就称为不可重复读,因为T1元来读取的那行记录已经发生了变化。
  • 幻读:一个事务重新执行一个查询,返回一套符合查询条件的行,发现这些行因为其他最近提交的事务而发生了变化。事务T1读取一条指定的where语句所返回的结果集。然后事务T2新插入一行记录,这行记录正好可以满足T1所使用的查询条件。然后T1又使用相同的查询再次对表进行检索。但是此时却看到了事务T2刚才插入的新行。这个新行就称为幻象,因为对T1来说这一行就像突然出现的一样(大部分数据库缺省的事务隔离级别都会出现这种状况,此种事务隔离级别将带来表级锁)

事务隔离级别描述

  • read uncommitted : 幻读,不可重复读和脏读均允许
  • read commited:允许幻读和不可重复读,但不允许脏读
  • repeatable read:允许幻读,但不允许不可重复读和脏读
  • serializable:幻读,不可重复读和脏读都不允许
    oracle默认的是 read commited
    MySQL默认的是 repeatable read

如果数据库的隔离级别为read uncommitted,则其他线程可以看到未提交的数据,因此就出现脏读。如果数据库隔离级别设为read committed,即没提交的数据别人是看不见的,就避免了脏读;但是,正在读取的数据只获得了读取锁,读完之后就解锁,不管当前事务有没有结束,这样就容许其他事务修改本事务正在读取的数据,导致不可重复读。repeatable read因为对正在操作的数据加锁(行级锁),并且只有等到事务结束才放开锁,则可以避免不可重复读。repeatable read只能保证正在被本事务操作的数据不被其他事务修改,却无法保证有其他事务提交新的数据。则有可能线程1在操作表T1的时候(特别是统计性的事务),其他线程仍然可以提交新数据到表T1,这样会导致线程1两次统计的结果不一致,就像发生幻觉一样。serializable因为获得范围锁,且事务是一个接着一个串行执行,则保证了不会发生幻读。由此可见,隔离级别越高,受其他事物干扰越少,并发性能越差。


修改事务的隔离级别

查看InnoDB系统级别的事务隔离级别

select @@global.tx_isolation;
  • 1

查看InnoDB会话级别的事务隔离级别

select @@tx.isolation;
  • 1

修改事务隔离级别

set global transaction isolation level read committed;set session transaction isolation level read committed;