JDBC_07悲观锁和乐观锁

JDBC_07悲观锁和乐观锁

1.悲观锁和乐观锁的概念

1.1悲观锁

在这里插入图片描述

悲观锁就是比较悲观。我在拿一条记录时,生怕别人修改这条记录,于是就把它锁住,不让别人用。直到我使用完才解锁。

悲观锁的语法格式是:

select ... from ... where ... for update;

如:

select empno,ename,job,sal from emp where empno = 7499 for update;

在mysql中,当使用for update语句时,决定行锁还是表锁的是条件字段是否能使用索引(如主键、unique等)。

如果能则为行锁,不能则为表锁。

所以在使用悲观锁时,条件字段最好为主键或有unique约束的字段,锁别的可能会将整张表都锁住,导致程序执行效率降低。

1.2乐观锁

乐观锁就是比较乐观,当我要修改一条记录时,不怕被别人修改,所有人都可以拿来用。

当我修改完后,在提交前,会再看一眼这条记录的版本号:

  • 如果和被我修改之前的版本号一样,我就将修改的数据提交,然后更改版本号。
  • 如果和被我修改之前的版本号不一样,我就将我的操作回滚。

2.演示悲观锁机制

2.1用到的表

emp:

+--------+-----------+---------+
| ename  | job       | sal     |
+--------+-----------+---------+
| SMITH  | CLERK     | 1800.00 |
| ALLEN  | SALESMAN  | 1600.00 |
| WARD   | SALESMAN  | 1250.00 |
| JONES  | MANAGER   | 4975.00 |
| MARTIN | SALESMAN  | 1250.00 |
| BLAKE  | MANAGER   | 4850.00 |
| CLARK  | MANAGER   | 4450.00 |
| SCOTT  | ANALYST   | 3000.00 |
| KING   | PRESIDENT | 5000.00 |
| TURNER | SALESMAN  | 1500.00 |
| ADAMS  | CLERK     | 2100.00 |
| JAMES  | CLERK     | 1950.00 |
| FORD   | ANALYST   | 3000.00 |
| MILLER | CLERK     | 2300.00 |
+--------+-----------+---------+

2.2演示流程

编写程序A和程序B,分别代表事务A和事务B。

事务A执行:

select ename,job,sal from emp where job = 'MANAGER' for update;

事务B执行:

update emp set sal = sal + 1000 where job = 'MANAGER';

在程序A中,在提交事务处打一个断点,然后debug,让事务A停住,

此时,运行程序B,查看程序B的反应。

2.3程序源码

2.3.1程序A
package com.tsccg.jdbc.transaction;

import com.tsccg.jdbc.util.JdbcUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @Author: TSCCG
 * @Date: 2021/07/29 14:31
 * 演示悲观锁
 * 事务A
 */
public class TransactionDemo03 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtil.connect();
            //开启事务
            conn.setAutoCommit(false);
            //使用悲观锁锁住job为MANAGER的所有记录
            String sql = "select ename,job,sal from emp where job = ? for update";
            ps = conn.prepareStatement(sql);
            ps.setString(1,"MANAGER");

            rs = ps.executeQuery();
            while (rs.next()) {
                System.out.println(rs.getString("ename") + ","
                        + rs.getString("job") + ","
                        + rs.getDouble("sal"));
            }
            //提交事务(事务结束)
            conn.commit();
        } catch (SQLException throwables) {
            if (conn != null) {
                try {
                    //回滚事务(事务结束)
                    conn.rollback();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            throwables.printStackTrace();
        } finally {
            JdbcUtil.close(conn,ps,rs);
        }
    }
}
2.3.2程序B
package com.tsccg.jdbc.transaction;

import com.tsccg.jdbc.util.JdbcUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * @Author: TSCCG
 * @Date: 2021/07/29 14:41
 * 演示悲观锁
 * 事务B
 */
public class TransactionDemo04 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn = JdbcUtil.connect();
            conn.setAutoCommit(false);
            //使用悲观锁锁住job为MANAGER的所有记录
            String sql = "update emp set sal = sal + 1000 where job = ?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,"MANAGER");
            int count = ps.executeUpdate();
            System.out.println(count > 0 ? "修改成功" : "修改失败");
            conn.commit();
        } catch (SQLException throwables) {
            if (conn != null) {
                try {
                    conn.rollback();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            throwables.printStackTrace();
        } finally {
            JdbcUtil.close(conn,ps,null);
        }

    }
}

2.3开始演示

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TSCCG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值