mysql的事务原理、隔离机制及解决方案

概述:事务(Transaction),是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合。

事务的特征(ACID)又称基本要素:

原子性(Atomicity):将所有 SQL 作为原子工作单元执行,要么全部执行,要么全部不执行
一致性(Consistency):事务完成后,所有数据的状态都是一致的
隔离性(Isolation):如果有多个事务并发执行,每个事务作出的修改必须与其他事务隔离
持久性(Durability):即事务完成后,对数据库数据的修改被持久化存储

事务原理:

 实现事务采取了哪些技术以及思想?主要使用日志和锁

 1.原子性:使用 undo log ,从而达到回滚

 2.持久性:使用 redo log,从而达到故障后恢复

 3.隔离性:使用锁以及MVCC,运用的优化思想有读写分离,读读并行,读写并行

 4.一致性:通过回滚,以及恢复,和在并发环境下的隔离做到一致性。

 事务并发容易产生的问题:

1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

解决方案:

1.针对脏读、不可重复读、幻读,都可设置共享锁(lock in share mode)或者排他锁(for update,行锁)进行限制,保证数据使用过程中的真实性;行锁无法解决幻读,需要表锁。

2.针对不可重复读还可以通过mysql的默认事务隔离机制或者设置事务隔离级别为REPEATABLE_READ(可重复读)。

lock in share mode 就是共享锁
如果事务对某行数据加上共享锁之后,可进行读写操作;其他事务可以对该数据加共享锁,但不能加排他锁,且只能读数据,不能修改数据。 某个事物想进行修改数据操作,那他必须等其他事物的共享锁都释放完毕才能进行修改操作

for update 排他锁,就是行锁
如果事务对数据加上排他锁之后,则其他事务不能对该数据加任何的锁。获取排他锁的事务既能读取数据,也能修改数据。

注:普通 select 语句默认不加锁,而CUD操作默认加排他锁。

事务隔离级别:

事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted)
不可重复读(read-committed)
可重复读(repeatable-read)
串行化(serializable)

mysql默认事务隔离级别为可重复读(repeatable-read),但是会有幻读的风险

Oracle默认事务隔离级别为不可重复读(read-committed)

串行化读(serializable)隔离机制最高,性能很低,一般很少用

      (串行化:事务在读操作时,先加表级别的共享锁,直到事务结束才释放

                      事务在写操作时,先加表级别的排它锁,直到事务结束才释放

                      串行化锁定了整张表,幻读不存在的!!!)

RR级别(repeatable-read)下如何解决幻读:

多版本并发控制(MVCC)+间隙锁(LOCK IN SHARE MODE)解决了幻读的问题

查看MySQL当前事务隔离级别,默认为REPEATABLE-READ(可重复读)

mysql> SELECT @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
1 row in set (0.00 sec)

MySQL默认操作模式为自动提交模式

mysql> select @@autocommit;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    7839
Current database: db

+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
1 row in set (0.13 sec)

你可能感兴趣的