0.README
本文介绍了事务的基本概念,常用的四个命令,事务的四个特性,最后介绍多事务处理中的可能出现的三种问题,以及对应的四个隔离等级。
1.什么是事务
事务处理用来维护数据库的完整性,保证成批的MySQL操作要么完全执行,要么完全不执行。
比如,假设有两个表,账户表money,和支出表pay,那么每一笔支出记录对应就要从余额表中删除一定金额,如果pay插入成功,money修改失败,那么就会造成数据不一致。
MySQL事务操作:
命令 | 含义 |
---|---|
START TRANSACTION; |
开启事务。后面的语句处于同一个事务之中 |
ROLLBACK [TO save_point_name]; |
回滚到指定的保留点,或者开启事务之前,结束事务 |
COMMIT |
提交事务,然后结束事务 |
SAVEPOINT |
保留点 |
示例:
mysql> SELECT * FROM ordertotals;
+-----------+-----------------+-------------+
| order_num | total_not_taxed | total_taxed |
+-----------+-----------------+-------------+
| 20005 | 149.87 | 222.00 |
| 20009 | 38.47 | 40.78 |
| 20006 | 55.00 | 58.30 |
| 20007 | 1000.00 | 1060.00 |
| 20008 | 125.00 | 132.50 |
| 20008 | 125.00 | 132.50 |
| 11111 | 100.00 | 125.00 |
| 11111 | 100.00 | 125.00 |
+-----------+-----------------+-------------+
8 rows in set (0.00 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> DELETE FROM ordertotals WHERE order_num = 11111;
Query OK, 2 rows affected (0.00 sec)
mysql> SELECT * FROM ordertotals;
+-----------+-----------------+-------------+
| order_num | total_not_taxed | total_taxed |
+-----------+-----------------+-------------+
| 20005 | 149.87 | 222.00 |
| 20009 | 38.47 | 40.78 |
| 20006 | 55.00 | 58.30 |
| 20007 | 1000.00 | 1060.00 |
| 20008 | 125.00 | 132.50 |
| 20008 | 125.00 | 132.50 |
+-----------+-----------------+-------------+
6 rows in set (0.00 sec)
mysql> ROLLBACK;
Query OK, 0 rows affected (0.01 sec)
mysql> SELECT * FROM ordertotals;
+-----------+-----------------+-------------+
| order_num | total_not_taxed | total_taxed |
+-----------+-----------------+-------------+
| 20005 | 149.87 | 222.00 |
| 20009 | 38.47 | 40.78 |
| 20006 | 55.00 | 58.30 |
| 20007 | 1000.00 | 1060.00 |
| 20008 | 125.00 | 132.50 |
| 20008 | 125.00 | 132.50 |
| 11111 | 100.00 | 125.00 |
| 11111 | 100.00 | 125.00 |
+-----------+-----------------+-------------+
8 rows in set (0.00 sec)
mysql>
MySQL中默认每个非事务语句都是自动提交的,可以通过 mysql> SET autocommit=0;
来设置为不自动提交,这里的提交是相对于客户端程序而言的,未提交时,一个客户端程序仍可以查看到自己修改的内容,断开连接后修改的内容就失效,只有在断开连接前提交,才能在服务器产生永久性修改。
在开启事务之后,必须手动用COMMIT
来提交事务。
2.事务的四个特性
原子性:原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如转账:支付前money+pay=2000;支付后money+pay2000。
隔离性:事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
持久性:指一个事务一旦被提交,它对数据库中数据的改变就是永久性的。
3.多事务的问题
当多个客户端线程执行数据库操作时,可能出现三种问题:
脏读:一个线程中的事务读到了另一个线程中事务未提交的数据。
不可重复读:一个线程中的事务读到了另一个线程中提交的update的数据,前后两次读到的内容不一致。
虚读:一个线程中的事务读到了另一个线程中提交的insert或delete的数据,前后读到的记录条数不一致。
4.事务的隔离级别
为了解决这些问题,数据库管理软件采用了一些·办法设置了事务的隔离等级。隔离等级越高,数据越安全,但性能越低。
隔离等级 | 脏读 | 不可重复读 | 虚读 |
---|---|---|---|
READ UNCOMMITTED(未提交读) | 可能 | 可能 | 可能 |
READ COMMITTED(提交读)Oracle默认 | 避免 | 可能 | 可能 |
REPEATABLE READ(可重复读)MySQL默认 | 避免 | 避免 | 可能 |
SERIALIZABLE(可序列化) | 避免 | 避免 | 避免 |
MySQL查看当前数据库的隔离级别命令是:
mysql> SELECT @@tx_isolation;
更改隔离级别(开启事务之前更改):
mysql> SET TRANSACTION ISOLATION LEVEL [level_name]