事务
多条语句同时成功或同时不成功,有一条失败会回滚,所有事务操作取消
- 用 BEGIN, ROLLBACK, COMMIT 来实现
- BEGIN 或 START TRANSACTION; 开始一个事务
- ROLLBACK 事务回滚
- COMMIT 事务确认
- 直接用 SET 来改变 MySQL 的自动提交模式:
- SET AUTOCOMMIT=0 禁止自动提交
- SET AUTOCOMMIT=1 开启自动提交
START TRANSACTION; // 开启事务
INSERT INTO stu (class_id,sname,sex)VALUES(2,'xx','x');
COMMIT;
四大特性
- 原子性:不能部分执行,事务不能完成也要回滚消除影响
- 侧重事务本身的职责,不管具体内容,只管能不能完成事务。
- 一致性:事务操作就是把数据库从一个状态到另一个状态。
- 侧重事务完成的结果
- 比如A和B都有1000,总共2000。A向B转账500,那么必须保持事务发生后A B都为1000
- A 减少500 和 B增加500
- 这两个操作必须在事务内全部得到实现
- 隔离性:多事务并发运行,各自执行各自的,互不影响
- 持久性:数据库出错也能恢复,或者事务提交后不会再发生意外改变
隔离问题
脏读:A读取了B事务过程中(未提交)的数据,但B后面进行了回滚。A读取到的即为脏数据
不可重复读:相对于
update
A
多次读取同一数据B
的事务在A
事务多次读取的过程中进行了更新并提交A
多次读取的结果不一致
幻读:相对于
insert
和delete
操作A
将数据库中所有成绩从*具体分数*改为ABCD等级- 但
B
这个时候插入了*具体分数*记录 A
改结束,发现有一条记录没改过来,像出现幻觉一样
不可重复读的和幻读很容易混淆,不可重复读侧重于
修改
,幻读侧重于新增
或删除
。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表四种隔离级别
隔离级别
事务隔离级别 | 脏读 | 不可重复读 | 幻读 | 说明 |
---|---|---|---|---|
读未提交(read-uncommitted) | 是 | 是 | 是 | 最低的事务隔离级别,一个事务还没提交时,它做的变更就能被别的事务看到 |
不可重复读(read-committed) | 否 | 是 | 是 | 保证一个事物提交后才能被另外一个事务读取。另外一个事务不能读取该事物未提交的数据。 |
可重复读(repeatable-read) | 否 | 否 | 是 | 多次读取同一范围的数据会返回第一次查询的快照,即使其他事务对该数据做了更新修改。事务在执行期间看到的数据前后必须是一致的。 |
串行化(serializable) | 否 | 否 | 否 | 事务 100% 隔离,可避免脏读、不可重复读、幻读的发生。花费最高代价但最可靠的事务隔离级别。 |
控制和查询
select @@tx_isolation; // 查询隔离级别
set session transaction isolation level read uncommitted; // 设置隔离级别
PHP实现
// mysql
mysql_query("COMMIT");//提交事务
mysql_query("ROLLBACK");//至少有一条sql语句执行错误,事务回滚
mysql_query("END");//事务结束
// mysqli
$conn = mysqli_connect('127.0.0.1', 'root', 'root') or die(mysqli_error()); //连接数据库
mysqli_query($conn, 'BEGIN'); //开启事务
mysqli_query($conn, 'COMMIT'); //提交事务
mysqli_query($conn, 'rollBack'); //回滚事务
//PDO
$pdo->beginTransaction(); //开启事务
$pdo->commit(); //提交事务
$pdo->rollBack(); //回滚事务
$pdo->end(); //结束事务
// Laravel
// 方法一,transaction方法
DB::transaction(function () {
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->delete();
});
// 方法二、手动事务
DB::beginTransaction(); //开启事务
DB::commit(); //事务提交
DB::rollBack(); // 事务回滚