事务

事务是一组原子性的SQL语句,理解事务最常用的例子就是银行转账:

A转给B100元钱,这个存储过程包含:

  1. A账户钱减少100元
  2. B账户钱增加100元

如果执行完第一步的SQL语句,但是因为系统崩溃等原因,导致第二条SQL语句没能正常执行,那么两个账户的总钱数就莫名其妙的少了100元。因此我们需要引入事务的概念,让这两步操作合成为一个原子操作,只有当两步操作全部正确完成时,事务提交,改动生效,否则事务回滚,恢复为初始状态。

MySQL中使用事务

下面我们以例子的形式演示MySQL种事务的使用,表结构定义如下。

create table t_person(
    person_id bigint auto_increment primary key,
    name varchar(255)
);

下面例子我们使用事务插入数据。

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t_person(name) values ("Tom");
Query OK, 1 row affected (0.00 sec)

mysql> insert into t_person(name) values ("Bob");
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.07 sec)

mysql> select * from t_person;
+-----------+------+
| person_id | name |
+-----------+------+
|         1 | Tom  |
|         2 | Bob  |
+-----------+------+
2 rows in set (0.00 sec)

在MySQL终端中,我们使用了begincommit命令,这两个命令代表着事务的开始和结束。

在存储过程中使用事务

存储过程中,使用一下三条语句表示事务的开始,提交和回滚。

START TRANSACTION;
COMMIT;
ROLLBACK;

事务的隔离级别

我们知道数据库有一个线程安全问题,因此引入了锁的概念,锁主要分为:共享锁和排它锁。MySQL中可以显式的使用锁,但是除此之外还有隐式的锁。隐式锁通过隔离级别,由MySQL和存储引擎自动指定。这里我们主要介绍MySQL的隐式的锁和隔离级别。

数据库隔离级别

以下四个隔离级别依次递增。

READ UNCOMMITTED

最低的隔离级别,所有事务都能看到尚未提交的事务的执行结果(脏读问题)。

READ COMMITTED

一个事务从开始到提交前,所做的任何数据改变,都是不可见的,直到该事务提交。但是这还是存在一个问题,即一个执行过程中的事务会读到另一个已提交事务对数据的更改(不可重复读问题)。

REPEATABLE READ

该级别在一次事务中,读相同的某一条数据,只能读到相同的值。避免了不可重复读问题。但是,还是存在问题的,如果另一个事务执行了插入操作,那么新插入的值还是会被当前事务读到(幻读问题)。

该级别是MySQL默认的隔离级别。

SERIALIZABLE

最高隔离级别,解决上述三个问题,但是性能较差。

MySQL会根据设置的隔离级别,自动使用合适的锁机制,实现线程安全。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。