数据库可不仅仅只有CRUD!关于事务了解多少!

本文首发于CSDN博客ityanger的同名文章:数据库可不仅仅只有CRUD!关于事务了解多少!.
关于MySQL的基础可以看我的上一篇博客:初学者不点进去就太亏了,MYSQL数据库超全知识点总结!

1 事务

Transaction其实指的一组操作,里面包含许多个单一的逻辑。只要有一个逻辑没有执行成功,那么都算失败。所有的数据都回归到最初的状态(回滚)

  • 为什么要有事务?

为了确保逻辑的成功。例子:银行的转账。

1.1 命令行演示

  1. 开启事务

    start transaction;
    
  2. 提交或者回滚事务

    commit; -- 提交事务,数据将会写到磁盘上的数据库
    rollback; -- 数据回滚,回到最初的状态。
    
  3. 关闭自动提交功能
    关闭自动提交功能
  4. 演示事务
    演示事务

1.2 代码演示

代码里面的事务,只是针对连接连接对象,如果再开一个连接对象,那么那是默认的提交。

  1. 通过conn.setAutoCommit(false);来关闭自动提交的设置。
  2. 提交事务conn.commit();
  3. 回滚事务conn.rollback();
    @Test
    public void testTransaction(){
        
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = JDBCUtil.getConn();
            // 连接,事务默认就是自动提交的。关闭自动提交。
            conn.setAutoCommit(false);
            String sql = "update account set money = money - ? where id = ?";
            ps = conn.prepareStatement(sql);
            // 扣钱,扣ID为1的100块钱
            ps.setInt(1, 100);
            ps.setInt(2, 1);
            ps.executeUpdate();
            int a = 10 / 0 ;
            
            //加钱,给ID为2 加100块钱
            ps.setInt(1, -100);
            ps.setInt(2, 2);
            ps.executeUpdate();
            //成功: 提交事务。
            conn.commit();
            
        } catch (SQLException e) {
            try {
                //事变:回滚事务
                conn.rollback();
            } catch(SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            JDBCUtil.release(conn, ps, rs);
        }
    }
    

1.3 事务的特性

  • 原子性: 事务中包含的逻辑,不可分割。

  • 一致性: 事务执行前后。数据完整性

  • 隔离性: 事务在执行期间不应该受到其他事务的影响

  • 持久性: 事务执行成功,那么数据应该持久保存到磁盘上

1.4 事务的安全隐患

不考虑隔离级别设置,那么会出现以下问题。

1.4.1 读

脏读、不可重读读、幻读.

  1. 脏读: 一个事务读到另外一个事务还未提交的数据
  2. 不可重复读: 一个事务读到了另外一个事务提交的数据 ,造成了前后两次查询结果不一致。
  3. 幻读: 一个事务读到了另一个事务insert的数据,造成前后查询结果不一致

1.4.2 写

丢失更新

  1. 丢失更新: 如果多个线程操作,基于同一个查询结构对表中的记录进行修改,那么后修改的记录将会覆盖前面修改的记录,前面的修改就丢失掉了。

1.5 隔离级别

  1. 读未提交(Read uncommitted)

    引发问题:脏读

  2. 读已提交(Read committed)

    解决:脏读,引发:不可重复读

  3. 可重复读(Repeatable read)

    解决:脏读、不可重复读,未解决:幻读

  4. 可串行化(Serializable)

    解决:脏读、不可重复读、幻读

  • 按效率划分,从高到低

    读未提交 > 读已提交 > 可重复读 > 可串行化

  • 按拦截程度 ,从高到底

    可串行化 > 可重复读 > 读已提交 > 读未提交

  • MySQL 默认的隔离级别是: 可重复读

  • Oracle 默认的隔离级别是: 读已提交

√:可能出现  ×:不会出现 脏读 不可重复读 幻读
Read uncommitted
Read committed ×
Repeatable read × ×
Serializable × × ×

1.5.1 读未提交

  1. 查看事务的隔离级别
    -- 我安装的是MySQL8,原先的select @@tx_isolation;不能用了
    select @@transaction_isolation;
    
  2. 设置隔离级别为读未提交
    -- read uncommitted 读未提交
    set session transaction isolation level read uncommitted;
    
  3. 引发的问题:两个并发的事务,"事务A:更新"、"事务B:查询",事务B读取了事务A尚未提交的数据,即我们所说的脏读。

1.5.2 读已提交

  1. 设置隔离级别为读已提交,可解决脏读。
    -- read committed 读已提交
    set session transaction isolation level read committed;
    
  2. 引发的问题:两个并发的事务,"事务A:查询"、"事务B:更新",事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变,即我们所说的不可重复读。

1.5.3 不可重复读

  1. 设置隔离级别为不可重复读,可解决不可重复读。
    -- repeatable read 不可重复读
    set session transaction isolation level repeatable read;
    
  2. 引发的问题:两个并发的事务,"事务A:更新"、"事务B:更新",事务A事先更新了数据,事务B紧接着又把更新了回来,并提交了事务,而事务A再次读取该数据时,发现数据没有发生改变,即我们所说的幻读。

1.5.4 可串行化

  1. 设置隔离级别为可串行化,可解决一切问题。
    -- serializable 可串行化
    set session transaction isolation level serializable;
    
  2. 如果有一个连接的隔离级别设置为了串行化,那么谁先打开了事务,谁就有了先执行的权利,谁后打开事务,谁就只能等着,等前面的那个事务,提交或者回滚后,才能执行。这种隔离级别一般比较少用,容易造成性能上的问题,效率比较低。

1.6 锁机制

  1. 解决丢失更新问题
    • 悲观锁(Pessimistic Locking)
    • 乐观锁(Optimistic Locking)

1.6.1 悲观锁

  1. 悲观锁原理:使用数据库内部锁机制,进行数据库表的锁定。就是在A管理员修改数据时,A管理员就将数据锁定,此时B管理员无法进行修改、查询。避免两个事务同时修改,也就解决了丢失更新问题。
  2. 在查询的时候,加入for update

1.6.2 乐观锁

  1. 乐观锁原理:使用的不是数据库的锁机制,而是一个特殊标记字段,通过控制字段状态和内容得知数据是否发生了并发访问。进行数据修改时,数据库会检测version字段或者时间戳是否与原来的一致。若不一致,抛出异常,提醒更新。
  2. 要求程序员自己控制。可以通过给数据表添加自增的version字段或时间戳timestamp

END

感谢看到这里的各位读者朋友们,如果你感到本文写的不错,就顺手点个赞👍收藏一下,也可以关注一波~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352