MySQL事务详解

MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在银行系统中,要添加一个账户,就要添加一个账户的基本信息,也要添加和该账户相关的信息,如联系电话等等,这些数据库操作语句就构成了一个事务。

一、事务的概念及特点

  • 在 MySQL 中只有使用了Innodb
    数据库引擎的数据库或表才支持事务。(MySQL5.7默认使用Innodb存储引擎)。
  • 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
  • 事务用来管理 insert,update,delete 语句。
  • 在 MySQL 命令行的默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要开启一个事务务须使用命令 BEGIN 或者执行命令 SET AUTOCOMMIT=0,用来禁止使用当前会话的自动提交。

一般来说,事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)

(1) 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

(2) 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。

(3) 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。

(4)持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。一旦事务被提交,事务的结果会被永久的保留到数据库中。

二、事务控制语句:

BEGIN :开启一个事务,后面有多条数据库操作语句执行;

COMMIT:提交事务,并使已对数据库进行的所有修改称为永久性的;

ROLLBACK:回滚会结束用户的事务,并撤销正在进行的所有未提交的修改;

SAVEPOINT identifier:SAVEPOINT允许在事务中创建一个保存点,一个事务中可以有多个SAVEPOINT;

RELEASE SAVEPOINT identifier:删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常;

ROLLBACK TO identifier:把事务回滚到标记点;

SET TRANSACTION:用来设置事务的隔离级别。InnoDB存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。

三、MYSQL 事务处理主要有两种方法:

1、用 BEGIN, ROLLBACK, COMMIT来实现

BEGIN 开始一个事务

ROLLBACK 事务回滚

COMMIT 事务确认

2、直接用 SET 来改变 MySQL 的自动提交模式:

SET AUTOCOMMIT=0 禁止自动提交

SET AUTOCOMMIT=1 开启自动提交

四、事务测试

  1. 创建好数据库和表
mysql> create database test;
Query OK, 1 row affected (0.01 sec)

mysql> use database test;
ERROR 1049 (42000): Unknown database 'database'
mysql> use test;
Database changed
mysql> create table info (id int(5)) engine=innodb;
Query OK, 0 rows affected (0.04 sec)

mysql> select * from info;
Empty set (0.08 sec)

mysql> 

2.在数据表info中插入2条数据,使用begin开始事务,并进行提交。

(1)不用commit提交,在当前的事务中可以查询到数据,但是数据不会出现在数据表中。

mysql> begin;   #开始事务
Query OK, 0 rows affected (0.00 sec)

mysql> insert into info (id) values(3);
Query OK, 1 row affected (0.01 sec)

mysql> insert into info (id) values(4);
Query OK, 1 row affected (0.00 sec)

mysql> select * from info;     #在当前事务中能查询到数据
+------+
| id   |
+------+
|    3 |
|    4 |
+------+
2 rows in set (0.00 sec)
mysql> exit;        #退出mysql连接
Bye

[root@localhost ~]# mysql -u root -p  #重新进mysql数据
Enter password: 
..........       #省略部分信息

mysql> use test;
Database changed

mysql> select * from info;  #查看commit未提交的数据表
Empty set (0.00 sec)

mysql> 

(2)commit提交事务后,数据出现在数据表中

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

mysql> insert into info (id) values(3);
Query OK, 1 row affected (0.00 sec)

mysql> insert into info (id) values(4);
Query OK, 1 row affected (0.00 sec)

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

mysql> select * from info;   
+------+
| id   |
+------+
|    3 |
|    4 |
+------+
2 rows in set (0.00 sec)
mysql> exit;        #退出mysql连接
Bye

[root@localhost ~]# mysql -u root -p  #重新进mysql数据
Enter password: 
..........       #省略部分信息

mysql> use test;
Database changed

mysql> select * from info;     #查看commit提交的数据表
+------+
| id   |
+------+
|    3 |
|    4 |
+------+
2 rows in set (0.00 sec)

mysql> 

3.插入一条数据后,使用rollback恢复到插入前数据的状态。

mysql> begin;            #开始事务
Query OK, 0 rows affected (0.00 sec)

mysql> insert into info (id) values (5);  #插入一条数据
Query OK, 1 row affected (0.00 sec)

mysql> rollback;                        #回滚
Query OK, 0 rows affected (0.00 sec)

mysql> select * from info;       #因为回滚所以数据没有插入
+------+
| id   |
+------+
|    3 |
|    4 |
+------+
2 rows in set (0.00 sec)

mysql> 

4.插入一条数据,使用savepoint定义回滚点,当出现误操作时,rollback可以决定回滚到的位置,再用commit命令进行提交

mysql> begin;     #开始事务
Query OK, 0 rows affected (0.00 sec)

mysql> insert into info (id) values (5);
Query OK, 1 row affected (0.01 sec)

mysql> savepoint s1;           #定义回滚点s1
Query OK, 0 rows affected (0.00 sec)

mysql> insert into info (id) values (6);  #误操作
Query OK, 1 row affected (0.00 sec)

mysql> savepoint s2;           #定义回滚点s2
Query OK, 0 rows affected (0.00 sec)

mysql> rollback to savepoint s1;    #回滚到s1
Query OK, 0 rows affected (0.00 sec)

mysql> select * from info;
+------+
| id   |
+------+
|    3 |
|    4 |
|    5 |
+------+
3 rows in set (0.00 sec)

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

mysql> 

SET AUTOCOMMIT=0 相当于 BEGIN,测试方法如上述一样。

猜你喜欢

转载自blog.51cto.com/11134648/2139747
今日推荐