事务隔离级别
【并发读问题】
【第一类更新丢失】撤销时,覆盖更新数据。
【脏读】读到未提交的更新。待定状态。
【虚读】其他事务已提交的插入数据。事务T1读取某一数据后,事务T2对其做了修改,当事务T1再次读该数据时得到与前一次不同的值。
【不可重复读】未避免“随时更新”。一个事务对同一行数据重复读取两次,但是却得到了不同的结果。两次读取之间该数据被其它事务所修改。
【第二类丢失更新】覆盖已提交的更新。
3.1. 第一类丢失更新:撤消一个事务时,把其它事务已提交的更新的数据覆盖了。
3.2. 脏读:一个事务读到另一个事务未提交的更新数据。
3.3. 幻读:一个事务执行两次查询,但第二次查询比第一次查询多出了一些数据行。
3.4. 不可重复读:一个事务两次读同一行数据,可是这两次读到的数据不一样。
3.5. 第二类丢失更新:这是不可重复读中的特例,一个事务覆盖另一个事务已提交的更新数据。
|
【隔离级别】
1)未提交读(Read Uncommitted):SELECT语句以非锁定方式被执行,所以有可能读到脏数据,隔离级别最低。
2)提交读(Read Committed):【看到插入,看到更新】解决了脏读,但未解决不可重复读。
在trasaction A中读取数据时对记录添加共享锁,但读取结束立即释放。其它transaction B对这个记录的试图修改会一直等待直到A中的读取过程结束,而不需要整个trasaction A的结束。所以,在trasaction A的不同阶段对同一记录的读取结果可能是不同的。
可能发生的问题:不可重复读。
3)可重复读(Repeated Read):【看到插入,看不到更新】
在同一个事务内的查询都是事务开始时刻一致的,InnoDB的默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻读。这可以通过“共享读锁”和“排他写锁”实现。
对于读出的记录,添加共享锁直到transaction A结束。其它transaction B对这个记录的试图修改会一直等待直到trasaction A结束。
可能发生的问题:当执行一个范围查询时,可能会发生幻读(插入)。
4)串行读(Serializable):完全的串行化读,所有SELECT语句都被隐式的转换成SELECT ... LOCK IN SHARE MODE,即读取使用表级共享锁,读写相互都会阻塞。隔离级别最高。
添加范围锁(比如表锁,页锁等,关于range lock,我也没有很深入的研究),直到transaction A结束。以此阻止其它trasaction B对此范围内的insert,update等操作。
幻读,脏读,不可重复读等问题都不会发生。
【隔离级别设置】
select @@tx_isolation
set transaction isolation level read committed;
set global transaction isolation level read committed;
1)服务启动选项--transaction-isolation或在配置文件中设置:
[mysqld]transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE}
2)服务启动后的设置:
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
事务属性ACID
所谓原子性就是将一组操作作为一个操作单元,是原子操作,即要么全部执行,要么全部不执行。
2)一致性(Consistency)
事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。
3)隔离性(Isolation)
隔离性指并发的事务是相互隔离的。即一个事务内部的操作及正在操作的数据必须封锁起来,不被其它企图进行修改的事务看到。
4)持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。即一旦一个事务提交,DBMS(Database Management System)保证它对数据库中数据的改变应该是永久性的,持久性通过数据库备份和恢复来保证。