三、InnoDB表事务、隔离级别
1 事务
MYSQL中只有INNODB和BDB类型的数据表才能支持事务处理,其他的类型是不支持的。InnoDB表事务控制我们在第三章介绍InnoDB引擎的时候已经给出过一个简单例子。InnoDB默认的是自动提交,我们在前边的例子中在事务开始的时候执行了BEGIN和SET AUTOCOMMIT=0操作来保证事务的可用性。MYSQL事务控制有两种方式:
(1) 用begin,rollback,commit来实现(显式)
(2)直接用set来改变mysql的自动提交模式(隐式)begin *开始一个事务
rollback *事务回滚
commit *事务确认
MYSQL默认是自动提交的,也就是你提交一个QUERY,它就直接执行!我们
可以通过:
一个事务应用的简单例子:set autocommit=0 *禁止自动提交
set autocommit=1 *开启自动提交
2 隔离级别mysql> CREATE TABLE t (id INT) TYPE=InnoDB;
Query OK, 0 rows affected, 1 warning (0.45 sec)
![]()
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
![]()
mysql> insert into t values(1);
Query OK, 1 row affected (0.00 sec)
![]()
mysql> select * from t;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
![]()
mysql> rollback;
Query OK, 0 rows affected (0.08 sec)
![]()
mysql> select * from t;
Empty set (0.00 sec)
MYSQL提供四种事务隔离级别:
•序列化(SERIALIZABLE)
•可重复读(REPEATABLE READ)
•提交读(READ COMMITTED)
•未提交读(READ UNCOMMITTED)
未提交读——这通常称为 'dirty read':non-locking SELECT 的执行使我们不会看到一个记录的可能更早的版本;因而在这个隔离级别下是非 'consistent' reads;这级隔离级别的运作如同 READ COMMITTED。处于这个隔离级的事务可以读到其他事务还没有提交的数据。如果这个事务使用其他事务未提交的变化作为计算的基础,然后那些未提交的变化被他们的父事务撤销,则会导致误差。
提交读——在一个事务中已经COMMIT的数据可以在其他事务中看到。如果这个事务频繁提交的话,其他的大的查询事务中可能会得到多个不同的结果。
可重复读——这是 InnoDB 默认的事务隔离级。在一个事务中所有读都是连续的。
序列化——提供最大程度的隔离,如果每个事务都以这种隔离级运行就会影响Mysql的性能,因为需要大量的资源来使大量事务在任一时刻不被看到。如果一个事务在执行一个SELECT操作,另外的事务不允许执行UPDATE操作,这个隔离级别下的SELECT操作被阴式地转换为 SELECT ... LOCK IN SHARE MODE。
设置事务的隔离级别:
需要super优先权执行这个操作。SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
取得当前事务的隔离级别:
默认情况下,隔离级别变量的值是基于每个会话设置的,但是可以通过添加global关键字对所有的会话进行全局设置。mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.44 sec)
REPEATABLE READ级别事务一致读的例子(显式):
SESSION 1:
SESSION 2:mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
![]()
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
![]()
mysql> insert into t values(1);
Query OK, 1 row affected (0.05 sec)
![]()
mysql> select * from t;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
SESSION 1:mysql> begin;
Query OK, 0 rows affected (0.00 sec)
![]()
mysql> select * from t;
Empty set (0.00 sec)
SESSION 2:mysql> COMMIT;
Query OK, 0 rows affected (0.08 sec)
REPEATABLE READ级别事务一致读的例子(隐式):mysql> select * from t;
Empty set (0.00 sec)
![]()
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
![]()
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
![]()
mysql> select * from t;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
![]()
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
![]()
SESSION 1:
SESSION 2:mysql> set autocommit=0;
Query OK, 0 rows affected (0.01 sec)
![]()
mysql> insert into t values(2);
Query OK, 1 row affected (0.00 sec)
![]()
mysql> select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
+------+
2 rows in set (0.01 sec)
SESSION 1:mysql> select @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 0 |
+--------------+
1 row in set (0.00 sec)
![]()
mysql> select * from t;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
SESSION 2:mysql> commit;
Query OK, 0 rows affected (0.06 sec)
![]()
mysql> insert into t values(3);
Query OK, 1 row affected (0.00 sec)
![]()
mysql> select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)
SESSION 1:mysql> select * from t;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
![]()
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
![]()
mysql> select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
+------+
2 rows in set (0.00 sec)
SESSION 2:mysql> commit;
Query OK, 0 rows affected (0.06 sec)
![]()
mysql> select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.05 sec)
mysql> select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
+------+
2 rows in set (0.00 sec)
![]()
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
![]()
mysql> select * from t;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)
