MySQL最终弹-并发(脏读,不可重复读,幻读及区别),JDBC的使用和安装,最全万字

这篇具有很好参考价值的文章主要介绍了MySQL最终弹-并发(脏读,不可重复读,幻读及区别),JDBC的使用和安装,最全万字。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、💛并发基本概念

 

并发的基本意思:

什么是并发呢?简单的理解就是同一时间执行

服务器同一时刻,给多个客户端提供服务~~,这两个客户端都可以给服务器提交事务。

如果提交两个事务,改不同的表还没啥影响,假如要改相同的表,这时候可能会出现麻烦。

二、💙 脏读

由并发产生的第一个问题——脏读,什么是脏读呢?就是有脏数据(就是临时的数据,不是最终数据)就比如说我改完代码,还没有提交数据库,你正在读,这样你读的数据和我改的数据有偏差,也就是你读的都是错误的数据就叫脏读👴

那么我们如何解决脏读呢?🌸🌸🌸

我们要给写操作加锁,当事务A正在写的时候,事务B就不可以读取了,知道事务A写完为止,提交其他事务的事务B,才可以读取事务A

引入了写加锁,降低了两个事务的并发性,提高了隔离性。降低了效率,却提高了稳定性

 三、 💜不可重复读

有并发产生的第二个问题——不可重复读,什么是不可重复读呢?

同一个读取数据的事务中,可能会涉及到多次读的操作,多次读的数据不同

比如:我在写代码,同学们正在看我写代码,他们看的时候我正在修改,然后我就继续修改完事,同学们是一直都在执行看我代码这一个事务,在第一眼看和后面看的数据结果不同。

那我们该怎么解决不可重复读呢?🐬 🐬 🐬 

那就是给读操作加锁~(写操作加锁:是我写的时候别人不可以读。给读操作加锁是:别人在执行读的过程的时候,我可以再开一个事务去写,在第二个事务开始之前,其他读事务,读到的就是旧数据,第二个事务提交之后,别人再读就是新版数据了)

注意哈脏读和不可重复读肯容易混: 🍎 🍎 🍎

不可重复读是一个事务要多次读取,然后有个小傻子在啪啪的改,写完你第一次读和第二次读的数据不一样。

脏读是一个小帅哥在写完了,但是还没交,这时候一个小傻子过来读取数据,发现的读的数据全是错的数据,毕竟我还没交,交完才是正确的。

四、💚 幻读

我在写代码的时候已经加上了读加锁,写加锁的情况下 

同学们正在看的事务,我没修改,我只是又增加了一些东西,(读着读着多个类啥的这种问题)

我们该如何解决幻读呢,办法只有一个了,就是串行化~彻底放弃并发性,执行事务,所有的事务都是一个挨着一个多串行执行(执行完一个事务,再去执行下一个事务)并发性最低的,隔离性是最高的,效率是最低的,数据也是最可靠的

MySQL提供了四种事务隔离级别

1.read uncommitted.  (存在脏读,不可重复读,幻读三种可能)隔离性最小,并发性最大,数据可靠性最低,效率最高

2.read committed(存在写加锁了)解决了脏读,其他两个还存在,隔离性上升,并发性下降,可靠性上升,效率下降

3.repeatable read(解决了脏读,不可重复读)给写,读加锁,存在幻读,隔离性上升,并发性下降,可靠性上升,效率下降

4.serializable :事务彻底串行执行,全解决了问题,隔离性最大,并发性最小,数据可靠性最高,效率最低


最终弹-完结篇最后一块

一、Java的JDBC编程🍭

通过java代码来操作数据库

 实际开发中,我们大部分都是使用代码去操作数据库(但是代码也是要依赖SQL的)

一个成熟的数据库一般都会提供有一些API(Application Programming interface 应用程序编程接口(广义概念))

提到接口大家肯定会想起来这个interface接口(特指java语法中一个特殊的语法格式(狭义上的概念)java中的interface也是一种提供API的方式

成熟的数据库会提供一些API供你使用(API有一些类的方法)

每个数据库的API制作者是不同的人,设计出来的API当然也会相差很多,这样往往会提高学习成本(于是老大哥java站出来了),让他们遵守一套统一的API,让所有数据库按照一样的方式进行操作使用(只要掌握一套API,就可以操作各种数据库)

MySQL最终弹-并发(脏读,不可重复读,幻读及区别),JDBC的使用和安装,最全万字,mysql,数据库数据库厂商会提供对应的代码,这个代码就完成针对API的转换

API:写了一个程序,这个程序要给比尔提供哪些功能,这些功能往往是通过函数/类这样的方式提供的(如之前的Random,Scanner,ArrayList,String)

那么java如何使用JDBC操作MySQL呢

1.创建一个项目,正常java的创建操作

2.引入MySQL的驱动包作为项目依赖,把驱动包下载出来,导入到项目中

那我们该如何下载呢

方法一:Oracle的官网去下载(但是不是很好用)

方法二:github

方法三:中央仓库->圈子里面的功德活佛,把知名的知名的第三方库都收放到一起了,知道去中央仓库找    https://mvnrepository.com/(牛逼的佬) ♐️  ♐️  ♐️ 

MySQL最终弹-并发(脏读,不可重复读,幻读及区别),JDBC的使用和安装,最全万字,mysql,数据库

 搜索完mysql之后,选择第二个,点击那个头像图片

MySQL最终弹-并发(脏读,不可重复读,幻读及区别),JDBC的使用和安装,最全万字,mysql,数据库

 翻地下寻找对应的版本,大版本相同就行,5.1就可以

点击那个版本号5.19

选择下面图的jar包就行,下载完事

☀️🌤☀️🌤☀️🌤☀️🌤

MySQL最终弹-并发(脏读,不可重复读,幻读及区别),JDBC的使用和安装,最全万字,mysql,数据库

 💫💫💫下一步,点击这里面的Directory ,名字可以写lib,把jar包,复制,粘贴,粘贴到lib里面.

MySQL最终弹-并发(脏读,不可重复读,幻读及区别),JDBC的使用和安装,最全万字,mysql,数据库

🌕🌕🌕

粘贴后,点击这个,然后点击OK就行。 

MySQL最终弹-并发(脏读,不可重复读,幻读及区别),JDBC的使用和安装,最全万字,mysql,数据库

🌗🌗🌗此时准备工作完成了,可以接下来写代码了

首先之前一直说Demo:例子, 以后找一些第三方库软件啥的可以用demo。

JDBC的流程(固定套路记住可以)

步骤一:创建数据源->数据库服务器是在哪里

你在之前自己建一个student(id name)的表

DataSource dataSource=new MysqlDataSource();

步骤二:(向上转型)

((MysqlDataSource)dataSource).setUrl();

给大家回顾一下,向上转型,和向下转型

向上转型:子类对象转成父类。

向下转型:父类对象转成子类。

实际上⚠️⚠️

MysqlDataSource dataSource=new MysqlDataSource();

dataSource.setUrl()其实就可以了 🌚 🌚 🌚

🍅🍅🍅

当然这么做肯定有他们的道理。

按照最初的转型方法,本质是希望让MysqlDataSource,不要扩散到代码的其他部分··思想其实是想降低mysql驱动包,和我们项目之间的耦合关系,避免后续更换数据库,成本过大。

Url:唯一资源定位符,通常用Url来描述网络上一个资源的位置,mysql本体是服务器~,相当于是网络上的资源,里面写的东西直接复制贴贴就行,不用背

"jdbc:mysql://127.0.0.1:3306/java108?characterEncoding=utf8&&useSSL=false"

这个是括号里面需要填写的,下面我们来分析一下每一块都是什么意思。

jdbc:mysql♈️url是一个什么类型的url ,这里的意思就是jdbc:mysql就是说给jdbc的mysql使用的。

127.0.0.1 ♉️网络上的一个地址~是通过这一串数字来表示的,这一串数字通常是4个部分,各个部分取值范围是0-255,4个部分使用,分割

3306♍️ 端号,区分主机上的应用程序

java108♋️数据库名字

characterEncoding=utf8&&useSSL=false; 统一字符集utf8

statement:是把sql原封不动的直接发给数据库服务器,数据库服务器自己解析sql

PreparedStatement,会先在客户端这边初步解析SQL(验证语法,是否正确),此时服务器就不用做这些检查了,从而降低服务器负担,另外,本身SQL存在String类型,JDBC提供statement对象,让我们把String对象转换成statement,再发给服务器执行,但是一般会使用PrparedStatement(预处理的语句)对象代替statement.

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;


public class Main {

   public static void main(String[] args) throws SQLException {

//1.创建数据源
      DataSource dataSource=new MysqlDataSource();
      ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java108?characterEncoding=utf8&&useSSL=false");
//设置你的数据库名字的密码,不是随便设置哈,你自己的数据库密码,root也是不能乱设置
      ((MysqlDataSource)dataSource).setUser("root");
      ((MysqlDataSource)dataSource).setPassword("lcl15604007179");


//2.和数据库服务器建立链接,认准第二个sql的Connection,第一个com那个是mysql的驱动包

      Connection connection=dataSource.getConnection();


//构造SQL语句
      String sql=" insert student values(1,'张三') ";
      PreparedStatement statement=connection.prepareStatement(sql);


//4.执行SQL语句
      int n=statement.executeUpdate();     //返回有几行收到了影响
      System.out.println(n);


//5.释放必要资源,关闭链接 -注意关闭顺序,后创建的先关闭
      statement.close();          //创建的对象都会持有一些计算机硬件,软件中资源
      connection.close();

   }
}

 🔯Java有垃圾回收机制,自动释放内存,但是资源不仅仅是内存啊,所以才需要关闭,资源需要手动关闭。

但是我们这么写,写出来的数据是写死的什么张三啥的,那我们该如何在动态的让用户输入数据呢,

PreparedStatement提供了我们占位符的写法,可以更优雅,更安全的解决上述问题

?是一个占位符,后续PreparedStatement会把变量数值带入到?中,

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;


public class Main {

   public static void main(String[] args) throws SQLException {

      Scanner scanner=new Scanner(System.in);
      System.out.println("输入姓名");
      String name=scanner.nextLine();
      System.out.println("输入数字");
      int id=scanner.nextInt();

//1.创建数据源
      DataSource dataSource=new MysqlDataSource();
      ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java108?characterEncoding=utf8&&useSSL=false");
      ((MysqlDataSource)dataSource).setUser("root");
      ((MysqlDataSource)dataSource).setPassword("lcl15604007179");


//2.和数据库服务器建立链接
      Connection connection=dataSource.getConnection();


//3.构造SQL语句
      String sql=" insert student values(?,?) ";
      PreparedStatement statement=connection.prepareStatement(sql);
      statement.setInt(1,id);          //表示的是第一个问号
      statement.setString(2,name);     //表示的是第二个问号


//4.返回受影响的行数
      int n=statement.executeUpdate();
      System.out.println(n);

//5.释放必要资源,关闭链接
      statement.close();
      connection.close();

   }
}

🔜就算是插入,修改,删除也没有区别,删除就是轻微的改动,下面的setString和SQL语句而已

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;


public class Main {

   public static void main(String[] args) throws SQLException {

      Scanner scanner=new Scanner(System.in);
      System.out.println("输入姓名");
      String name=scanner.nextLine();

//1.创建数据源
      DataSource dataSource=new MysqlDataSource();
      ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java108?characterEncoding=utf8&&useSSL=false");
      ((MysqlDataSource)dataSource).setUser("root");
      ((MysqlDataSource)dataSource).setPassword("lcl15604007179");

//2.和数据库服务器建立链接
      Connection connection=dataSource.getConnection();

//3.构造SQL语句
      String sql=" delete  from student  where  name=? ";
      PreparedStatement statement=connection.prepareStatement(sql);
      statement.setString(1,name);

//4.执行SQL语句
      int n=statement.executeUpdate();
      System.out.println(n);
//5关闭
      statement.close();
      connection.close();

   }
}

❤❤❤但是查询有说法,,一下就是查询要注意的操作。

 //4.执行查询操作,要使用excuteQuery,返回值是一个ResultSet类型的对象,表示了一个表格
      ResultSet resultSet = statement.executeQuery();
//遍历结果集合
      while (resultSet.next()) 

这个意思是什么捏?💝💝💝想象有一个光标,这个光标的初始情况下,指向第一行记录的前一个位置~

如果每次调用next为true,取这行数据 ,取完这一行,下次又要调用next,此时要是返回false,循环结束

MySQL最终弹-并发(脏读,不可重复读,幻读及区别),JDBC的使用和安装,最全万字,mysql,数据库

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;


public class Main {

   public static void main(String[] args) throws SQLException {

      Scanner scanner = new Scanner(System.in);

//1.创建数据源
      DataSource dataSource = new MysqlDataSource();
      ((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java108?characterEncoding=utf8&&useSSL=false");
      ((MysqlDataSource) dataSource).setUser("root");
      ((MysqlDataSource) dataSource).setPassword("lcl15604007179");

//2.和数据库服务器建立链接
      Connection connection = dataSource.getConnection();

//构造SQL语句
      String sql = " select * from student   ";
      PreparedStatement statement = connection.prepareStatement(sql);

//4.执行查询操作,要使用excuteQuery,返回值是一个ResultSet类型的对象,表示了一个表格
      ResultSet resultSet = statement.executeQuery();
//遍历结果集合
      while (resultSet.next()) {
//获取这一行学号列
         int id = resultSet.getInt("id");
//获取姓名列
         String name = resultSet.getString("name");
         System.out.println("id: " +  id + ",name: " + name);

      }
      statement.close();
      connection.close();
   }
}

当然里面也可以包含一些占位符。💖💖💖

public class Main {

   public static void main(String[] args) throws SQLException {

      Scanner scanner = new Scanner(System.in);
      int student_id=scanner.nextInt();

//1.创建数据源
      DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java108? characterEncoding=utf8&&useSSL=false");             
      ((MysqlDataSource) dataSource).setUser("root");
      ((MysqlDataSource) dataSource).setPassword("lcl15604007179");

//2.和数据库服务器建立链接
      Connection connection = dataSource.getConnection();

//注意哈,这里面是id不是你写的那个变量student_id
      String sql = " select * from student   where id = ? ";
      PreparedStatement statement = connection.prepareStatement(sql);
      statement.setInt(1,student_id);

//4.执行SQL语句
      ResultSet resultSet = statement.executeQuery();

      while (resultSet.next()) {
         int id = resultSet.getInt("id");
         String name = resultSet.getString("name");
         System.out.println("id: " +  id + ",name: " + name);
      }
//5.注意关闭的时候result也需要关闭
      resultSet.close();
      statement.close();
      connection.close();

   }
}

💟💟💟复杂的SQL也是这么写都支持(create table ,drop table都可以就是不推荐)

DataSource

Connection

PreparedStatement

Result

四大天王,通过这四个类,就可以基本吃遍JDBC编程

大佬会对JDBC进行进一步封装,数据库操作框架(虽然项目中不一定使用JDBC,一般都用框架代替,但是JDBC是不变化的,框架是可变的,基于JDBC去使用框架文章来源地址https://www.toymoban.com/news/detail-624620.html

到了这里,关于MySQL最终弹-并发(脏读,不可重复读,幻读及区别),JDBC的使用和安装,最全万字的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MySQL 幻读

    假设这样一个场景: 对于T3 查到的(0,0,5)不是幻读,T5查到的(1,1,5)才是幻读。( 幻读仅专指“新插入的行 ) 注:上面的图并不会实际发生,只是为了更好的引出问题而写的,实际上MySQL已经针对幻读问题做了解决方案(next-key lock下面讲),实际情况T5不会查到新

    2024年02月06日
    浏览(47)
  • MYSQL幻读问题

    “Phantom Problem是指在同一事务下,连续执行两次同样的SQL语句可能导致不同的结果,第二次的SQL语句可能会返回之前不存在的行。”摘录来自 MySQL技术内幕:InnoDB存储引擎(第2版) (数据库技术丛书) ​ 通俗来说就是,time1:事务A读取某个范围,time2:事务B在这个范围中插入了一条

    2024年02月13日
    浏览(35)
  • Mysql 幻读,当前读和快照读

    什么是幻读 幻读 指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户在读取该范围的数据行时,会发现有新增行数据; mysql 在RR(可重复读)隔离级别利用间隙锁机制下一定程度上解决了幻读。 这里的一定程度上 是指 只有 快照读 的情况。 当前读

    2024年02月12日
    浏览(41)
  • 你知道MySQL是如何解决幻读的吗?

    SQL标准中定义了4种隔离级别,分别是读未提交、读已提交、可重复读以及序列化。不同的隔离级别下,可以解决不同的并发问题,如下图所示。当然MySQL也基本遵循了这个标准,但是在实现上稍有不同。 本文重点探讨下MySQL是如何解决幻读问题的,首先 串行化 隔离级别铁定

    2024年02月05日
    浏览(41)
  • gin自定义中间件解决requestBody不可重复读问题

    先直接上代码 注意,上面的中间件,需要在第一个执行。 在gin中,context.Request.Body 是一个io.ReadCloser的接口,如下图 查看io.ReadCloser接口定义 我们发现io.ReaderCloser接口的本质就是 Read(p []byte) (n int, err error) 和 Close() error 的组合。 所以我们只需要自己编写实现 Read(p []byte) (n in

    2024年02月01日
    浏览(79)
  • MySQL 8.0 OCP认证精讲视频、环境和题库之四 多实例启动 缓存、事务、脏读

        1、编辑选项文件,指定以下选项:     [mysqld]         basedir=/mysql80         datadir=/mysql80/data1         socket=/mysql80/data1/mysqld.sock         pid-file=/mysql80/data1/mysqld.pid         log-error=/mysql80/data1/mysqld.log     2、初始化         /mysql80/bin/mysqld --defaults-file=/mys

    2024年02月07日
    浏览(38)
  • 【MySQL】MVCC是如何解决快照读下的幻读问题的

    我们从上文中了解到 InnoDB 默认的事务隔离级别是 repeatable read (后文中用简称RR),它为了解决该隔离级别下的幻读的并发问题,提出了 LBCC 和 MVCC 两种方案。其中 LBCC 解决的是当前读情况下的幻读, MVCC 解决的是普通读(快照读)的幻读。至于什么是当前读,什么是快照读

    2024年02月10日
    浏览(48)
  • 在项目中高并发场景怎么解决消息队列重复消费的解决思路

    1. 前端限制: 防抖和节流:在用户点击“下单”按钮时,使用防抖和节流技术限制用户在短时间内多次提交。 2. 后端接口处理: 分布式锁:当用户下单时,可以使用Redis或ZooKeeper实现的分布式锁,确保同一个用户在同一时间只能有一个订单请求被处理。 3. 订单唯一性设计:

    2024年02月13日
    浏览(34)
  • MYSQL数字函数:不可不知的数据处理利器

    🌈  个人主页: danci_ 🔥  系列专栏: 《MYSQL应用》 💪🏻  制定明确可量化的目标,坚持默默的做事。 MYSQL数字函数:不可不知的数据处理利器                在软件开发中,MySQL数字函数扮演着至关重要的角色,它们能够帮助我们快速地对数据进行数学运算、转换和处

    2024年04月10日
    浏览(72)
  • Prometheus结合Grafana监控MySQL,这篇不可不读!

    📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】!😜😜😜 中国DBA联盟(ACDU)成员,目前服务于工业互联网 擅长主流Oracle、MySQL、PG、高斯及Greenplum运维开发,备份恢复,安装迁移,性能优

    2024年03月12日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包