April 2, 2019 | 15:12

数据库-事务及其隔离问题

事务

多条语句同时成功或同时不成功,有一条失败会回滚,所有事务操作取消

  • 用 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多次读取的结果不一致
  • 幻读:相对于 insertdelete操作

    • 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();  // 事务回滚 

© Aris 2020
鄂ICP备18010884号-1

Powered by Hugo & Kiss'Em.