尚硅谷高频面试题第一季

尚硅谷面试题集(第一季)

1、自增变量

//代码如下
public class Main {
    public static void main(String[] args) {
        int i = 1;
        int j = i++;
        int k = i+++i*i++;
//        System.out.prinln(i+" "+j+" "+k);//i=4,j=1;k=11;
    }
}

字节码如下:

 0 iconst_1
 1 istore_1
 2 iload_1
 3 iinc 1 by 1
 6 istore_2
 7 iload_1
 8 iinc 1 by 1
11 iload_1
12 iload_1
13 iinc 1 by 1
16 imul
17 iadd
18 istore_3
19 return

图解如下:
在这里插入图片描述
2、单例模式

要点

一是某个类只能有一个实例;
构造器私有化
二是它必须自行创建这个实例;
含有一个该类的静态变量来保存这个唯一的实例
三是它必须自行向整个系统提供这个实例;
对外提供获取该实例对象的方式:
(1)直接暴露(2)用静态变量的get方法获取

(1)饿汉式

饿汉式:直接创建对象,不存在线程安全问题
直接实例化饿汉式(简洁直观)
枚举式(最简洁)
静态代码块饿汉式(适合复杂实例化)

代码如下:

//饿汉式单例:直接创建对象,不存在线程安全问题:不管是否需要都会创建
//1、直接实例化饿汉式(简单直观)
public class Singleton1 {
    //1、构造器私有化
    private Singleton1(){

    }
    //2、自行创建,并且用静态变量保存,为了强调这是个单例可用final修饰,使用final便不能 更改,public向外提供实例
    public final static Singleton1 INSTANCE = new Singleton1();
}

//饿汉式单例:直接创建对象,不存在线程安全问题:不管是否需要都会创建
//2、枚举:表示该类型的对象是有限的几个,我们可用限定一个便成立单例(最简洁)
//枚举的构造器全都是私有化,该模式等同于饿汉式直接实例
public enum  Singleton2 {
    INSTACE
}


//饿汉式单例:直接创建对象,不存在线程安全问题:不管是否需要都会创建
//3、静态代码块 饿汉式(适合复杂实例化)
public class Singleton3 {
    //1、构造器私有化
    private Singleton3(){

    }
    //2、自行创建,并且用静态变量保存,为了强调这是个单例可用final修饰,使用final便不能 更改,public向外提供实例
    public static final  Singleton3 INSTANCE;
    static {
        INSTANCE = new Singleton3();//有参数时最适合这种模式
    }
}

(2)懒汉式

懒汉式:延迟创建对象
线程不安全(适用于单线程)
线程安全(适用于多线程)
静态内部类形式(适用于多线程)

代码如下:

//懒汉式单例:延迟创建对象\
//1、线程不安全(适用于单线程)
public class Singleton4 {
    //1、构造器私有化
    private Singleton4(){

    }
    //2、用静态变量保存
    private static  Singleton4 INSTANCE;
    //3、提供一个静态方法,获取这个实例对象
    public static Singleton4 getInstance(){
        if(INSTANCE==null){
            try {
                Thread.sleep(100);//阻塞线程后如果两个线程进入,可能会造创建两个线程,
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE = new Singleton4();
        }
        return INSTANCE;
    }
}


//懒汉式单例:延迟创建对象\
//2、线程安全(适用于多线程)
public class Singleton5 {
    //1、构造器私有化
    private Singleton5(){

    }
    //2、用静态变量保存
    private static Singleton5 INSTANCE;
    //3、提供一个静态方法,获取这个实例对象
    public static Singleton5 getInstance(){
        if(INSTANCE==null){//优化线程
            synchronized (Singleton5.class){//添加同步块即可锁定该线程
                if(INSTANCE==null){
                    try {
                        Thread.sleep(100);//阻塞线程后如果两个线程进入,可能会造创建两个线程,
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE = new Singleton5();
                }
            }
        }


        return INSTANCE;
    }
}


//懒汉式单例:延迟创建对象\
//3、静态内部类形式(适用于多线程)代码简洁:在内部类被加载和初始化时才被创建INSTANCE实例对象
//静态内部类不会自动随着外部类的加载和初始化而被初始化,它是要单独去加载和初始化
//因为是在内部类加载和初始化时,创建的,因此线程安全
public class Singleton6 {
    //1、构造器私有化
    private Singleton6(){

    }
    //2、将静态变量存入内部类
    private static class Inner{
        //2.1、用静态变量保存
        private static final Singleton6 INSTANCE = new Singleton6();
    }
//    3、暴露接口
    public static Singleton6 getInstance(){
        return Inner.INSTANCE;
    }
}

小节:

如果是饿汉式,枚举形式最简单
如果是懒汉式,静态内部类形式最简单

3、类的初始化和实例初始化
在这里插入图片描述
考点:

类初始化过程
实例初始化过程
方法的重写

类初始化过程 :
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

4、方法的参数传递机制

在这里插入图片描述

考点?
方法的传递机制
String、包装类的等对象的不可变性

在这里插入图片描述

5、递归与迭代

编程题:有n步台阶,一次只能上1步或2步,共有多少种走法
1、递归
2、循环迭代

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

6、成员变量与局部变量

在这里插入图片描述

考点:
就近原则
变量的分类
	成员变量:类变量、实例变量
	局部变量
非静态代码块的执行:每次创建实例对象都会执行
方法的调用规则:调用一次,执行一次

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

7、Spring Bean的作用域之间的区别

<!-- ★bean的作用域
		可以通过scope属性来指定bean的作用域
			-singleton:默认值。当IOC容器一创建就会创建bean的实例,而且是单例的,每次得到的都是同一个
			-prototype:原型的。当IOC容器一创建不再实例化该bean,每次调用getBean方法时再实例化该bean,而且每调用一次创建一个对象
			-request:每次请求实例化一个bean
			-session:在一次会话中共享一个bean
	 -->
	<bean id="book" class="com.atguigu.spring.beans.Book" scope="prototype">
	 	<property name="id" value="8"></property>
	 	<property name="title" value="红高粱"></property>
	 	<property name="author" value="莫言"></property>
	 	<property name="price" value="10.00"></property>
	 	<property name="sales" value="800"></property>
	</bean>

在这里插入图片描述

8、Spring支持的常用数据库事务传播属性和…

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

当开启事务,@Transactional时,没有指定属性,则默认开启required,因为required特性,即如果事
务中进行两次操作,余额有100,买第一件要60,第二件要50,买完第一件则买第二件时失败,因为
要保持原子性,买第二件失败后回滚事务,第一件也回滚事务,则没有买成功。

如果改成propagation=Propagation.REQUIRED_NEW,则可以买成功第一件。
原因是因为当propagation=Propagation.REQUIRED时,开启买第一件和第二件的事务是同一个
,因为原子性,要么都成功,要么都失败,而当propagation=Propagation.REQUIRED_NEW时
,每次启动开启事务的方法时,其开启的是两个不同的事物,则第一件成功是一个事物,
第二件失败又是另一种事物,两种之间不影响。

在这里插入图片描述
在这里插入图片描述

代码如下

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

脏读:当前这个事务读到了其他事务更新但是还没提交的值就是脏读。

在这里插入图片描述
在这里插入图片描述

第一个级别,脏读,不可重复读,幻读都不能避免
第二个级别,不可重复读,幻读不能避免
第三级别:幻读不能避免
第四级别:都可以避免
但是效率从高到低。所以要合适使用,开发时一般用读已提交

9、SpringMVC中如何解决POST请求中文乱码,GET又如何处理

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="${pageContext.request.contextPath }/testPOJO" method="post">
		<!-- 表单项中的name属性值要与POJO类中的属性名保持一致 -->
		工号:<input type="text" name="id"><br>
		姓名:<input type="text" name="lastName"><br>
		邮箱:<input type="text" name="email"><br>
		部门编号:<input type="text" name="dept.id"><br>
		部门名称:<input type="text" name="dept.name"><br>
		<input type="submit">
	</form>
</body>
</html>

在这里插入图片描述

package com.atguigu.springmvc.handler;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.atguigu.springmvc.entities.Employee;

@Controller
public class SpringMVCHandler {
	
	public static final String SUCCESS="success";

	//1.SpringMVC中如何解决POST请求中文乱码问题,GET的又如何处理呢
	
	/*
	 * ★测试入参为POJO
	 * Spring MVC会按请求参数名和 POJO属性名进行自动匹配,
	 * 		    自动为该对象填充属性值。支持级联属性
	 */
	@RequestMapping("/testPOJO")
	public String testPOJO(Employee employee) {
		System.out.println("员工的信息是:"+employee);
		return SUCCESS;
	}
}

测试:

在这里插入图片描述

得出结果(中文乱码)
在这里插入图片描述

可以使用SpringMVC中的过滤器CharacterEncodingFilter

在这里插入图片描述

需要在web.xml中设置过滤器

在这里插入图片描述

之后需要设置拦截目标,常设置成拦截所有

在这里插入图片描述

在这里插入图片描述

如果改成get?

在这里插入图片描述

那么还是会乱码

解决:
1、在服务器中的server.xml中第一个Connector中添加属性URLEncoding=“UTF-8”,重启服务器

在这里插入图片描述

10、简单谈一下SpringMVC的工作原理

@Controller
public class SpringMVCHandler {
	
	public static final String SUCCESS="success";

	//1.简单的谈一下SpringMVC的工作流程
	
	//处理模型数据方式一:将方法的返回值设置为ModelAndView
	@RequestMapping("/testModelAndView")
	public ModelAndView testModelAndView() {
		//1.创建ModelAndView对象
		ModelAndView mav = new ModelAndView();
		//2.设置模型数据,最终会放到request域中
		mav.addObject("user", "admin");
		//3.设置视图
		mav.setViewName("success");
		return mav;
	}
	/*
	 * ★处理模型数据方式二:方法的返回值仍是String类型,在方法的入参中传入Map、Model或者ModelMap
	 * 	不管将处理器方法的返回值设置为ModelAndView还是在方法的入参中传入Map、Model或者ModelMap,
	 *  SpringMVC都会转换为一个ModelAndView对象
	 */
	@RequestMapping("/testMap")
	public String testMap(Map<String , Object> map) {
		//向Map中添加模型数据,最终会自动放到request域中
		map.put("user", new Employee(1, "韩总", "hybing@atguigu.com", new Department(101, "教学部")));
		return SUCCESS;
	}
}

在这里插入图片描述

/*①客户端的所有请求都交给前端控制器DispatcherServlet来处理,它会负责调用系统的其他模块来真正处理用户的请求。

②DispatcherServlet收到请求后,将根据请求的信息(URL、http协议方法、请求头、请求参数、cookie等)以及HandlerMapping的配置找到处理该请求的Handler(任何一个对象都可以作为请求的Handler)。

③在这个地方spring会通过HandlerAdapter对该处理器进行封装。

④HandlerAdapter是一个适配器,它用统一的接口对各种Handler中的方法进行调用。

⑤Handler完成对用户请求的处理后,会返回一个ModelAndView对象给DispatcherServlet,顾名思义,ModelAndView包含了数据模型以及相应的视图信息。

⑥ModelAndView的视图是逻辑视图,DisptcherServlet还要借助视图解析器ViewResolver完成从逻辑视图到真正视图的解析工作。

⑦当得到真正的视图对象后,DispatcherServlet会利用视图对象对模型数据进行渲染。

⑧客户端得到响应,可能是一个普通的html页面,也可以是json或xml数据,还可以是一张图片或pdf文件。

源码解析如下

1、发送请求

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a href="${pageContext.request.contextPath }/testModelAndView">Test ModelAndView</a><br>
	<a href="${pageContext.request.contextPath }/testMap">Test Map</a><br>
</body>
</html>

在这里插入图片描述

点击Test Map,发送请求进入testMap

/**
	 * Process the actual dispatching to the handler.处理实际分派给处理程序。


	 * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
	 处理程序将通过按顺序应用servlet的handler映射获得。
	 * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
	 HandlerAdapter将通过查询servlet已安装的HandlerAdapter获得


	 * to find the first that supports the handler class.
	 找到第一个支持handler类的。


	 * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
	 所有的HTTP方法都由这个方法处理。这取决于手持适配器或处理程序


	 * themselves to decide which methods are acceptable.
	 自己决定哪些方法是可以接受的。

	 * @param request current HTTP request 当前HTTP请求

	 * @param response current HTTP response 当前HTTP响应

	 * @throws Exception in case of any kind of processing failure 
	 如果出现任何处理故障
	 */
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				// Determine handler for the current request.
                //确定当前请求的处理程序。
                //其中mappedHandler就是HandlerExecutionChain对象,里边包含了所有的处理器和拦截器
				mappedHandler = getHandler(processedRequest);//getHandler源码如下
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
                //确定当前请求的处理程序适配器。
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

                //调用拦截器的方法
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

                //重点
				// Actually invoke the handler.实际调用处理程序。
                
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}

				applyDefaultViewName(processedRequest, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			catch (Throwable err) {
				// As of 4.3, we're processing Errors thrown from handler methods as well,
				// making them available for @ExceptionHandler methods and other scenarios.
				dispatchException = new NestedServletException("Handler dispatch failed", err);
			}
            //处理结果,源码如下方processDispatchResult
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Throwable err) {
			triggerAfterCompletion(processedRequest, response, mappedHandler,
					new NestedServletException("Handler processing failed", err));
		}
		finally {
			if (asyncManager.isConcurrentHandlingStarted()) {
				// Instead of postHandle and afterCompletion
				if (mappedHandler != null) {
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			}
			else {
				// Clean up any resources used by a multipart request.
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}




/**
	 * Return the HandlerExecutionChain for this request.
	 为此请求返回HandlerExecutionChain。
	 * <p>Tries all handler mappings in order.按顺序尝试所有处理程序映射。
	 * @param request current HTTP request 当前HTTP请求
	 * @return the HandlerExecutionChain, or {@code null} if no handler could be found
	 */
	@Nullable//如果可以传入NULL值,则标记为@Nullable,如果不可以,则标注为@Nonnull。
	protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			for (HandlerMapping hm : this.handlerMappings) {
				if (logger.isTraceEnabled()) {
					logger.trace(
							"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
				}
				HandlerExecutionChain handler = hm.getHandler(request);//此处得到HandlerExecutionChain对象
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

processDispatchResult源码:

/**
	 * Handle the result of handler selection and handler invocation, which is
	 * either a ModelAndView or an Exception to be resolved to a ModelAndView.
	 */
	private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
			@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
			@Nullable Exception exception) throws Exception {

		boolean errorView = false;
		//判断是否由异常
		if (exception != null) {
			if (exception instanceof ModelAndViewDefiningException) {
				logger.debug("ModelAndViewDefiningException encountered", exception);
				mv = ((ModelAndViewDefiningException) exception).getModelAndView();
			}
			else {
				Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
				mv = processHandlerException(request, response, handler, exception);
				errorView = (mv != null);
			}
		}

		// Did the handler return a view to render?
		if (mv != null && !mv.wasCleared()) {
			//渲染视图,源码如下render
			render(mv, request, response);
			if (errorView) {
				WebUtils.clearErrorRequestAttributes(request);
			}
		}
		else {
			if (logger.isDebugEnabled()) {
				logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
						"': assuming HandlerAdapter completed request handling");
			}
		}

		if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
			// Concurrent handling started during a forward
			return;
		}

		if (mappedHandler != null) {
			mappedHandler.triggerAfterCompletion(request, response, null);
		}
	}

render

/**
	 * Render the given ModelAndView.
	 * <p>This is the last stage in handling a request. It may involve resolving the view by name.
	 * @param mv the ModelAndView to render
	 * @param request current HTTP servlet request
	 * @param response current HTTP servlet response
	 * @throws ServletException if view is missing or cannot be resolved
	 * @throws Exception if there's a problem rendering the view
	 */
	protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
		// Determine locale for request and apply it to the response.
		Locale locale =
				(this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale());
		response.setLocale(locale);

		View view;
		String viewName = mv.getViewName();
		if (viewName != null) {
			// We need to resolve the view name.解析视图名
			view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
			if (view == null) {
				throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
						"' in servlet with name '" + getServletName() + "'");
			}
		}
		else {
			// No need to lookup: the ModelAndView object contains the actual View object.
			view = mv.getView();
			if (view == null) {
				throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
						"View object in servlet with name '" + getServletName() + "'");
			}
		}

		// Delegate to the View object for rendering.
		if (logger.isDebugEnabled()) {
			logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
		}
		try {
			if (mv.getStatus() != null) {
				response.setStatus(mv.getStatus().value());
			}
			view.render(mv.getModelInternal(), request, response);
		}
		catch (Exception ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Error rendering view [" + view + "] in DispatcherServlet with name '" +
						getServletName() + "'", ex);
			}
			throw ex;
		}
	}

内容太多了,不往下写了

须知最终是返回视图,并将之放入request域

在这里插入图片描述

获取转发器

在这里插入图片描述

进行转发

在这里插入图片描述

最终可在jsp中取到数据输出到页面中

详细解析

https://www.cnblogs.com/yoci/p/10642493.html

11、Mybatis中当实体类中的属性名和表中的字段名不一样,怎么办?

导致取值不到的现象
有三种解决方案
1.写sql语句时起别名

在这里插入图片描述

2.在MyBatis的全局配置文件中开启驼峰命名规则

在这里插入图片描述

3.在Mapper映射文件中使用resultMap来自定义映射规则

在这里插入图片描述

12、Linux常用服务类相关命令

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

13、git分支相关命令

在这里插入图片描述
在这里插入图片描述

14、redis持久化

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

15、Mysql什么时候建索引

索引是什么?
在这里插入图片描述

优势?
在这里插入图片描述

劣势?

在这里插入图片描述

在这里插入图片描述

那些情况不要创建索引?
在这里插入图片描述

16、JVM垃圾回收机制

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

我的理解

java垃圾回收机制?

在这里插入图片描述

GC发生在JVM那部分?

堆,方法区
在这里插入图片描述

jdk1.8及以后永久代改成元空间

有几种GC,他们的算法是什么?

java有4种,详情可看ppt

在这里插入图片描述

17、redis在项目中的应用场景

在这里插入图片描述

String:封锁一个IP地址:即是经常访问同一个IP地址。使用Incrby命令记录当前IP地址被次数
Hash:如果用String存储用户信息,当修改时,需要将全部的String用户信息反序列化,如果用Hash存储,需要修改什么就反序列化什么,因为序列化和反序列化都是要进行IO操作的,用String会增加IO次数,使用Hash比String性能要好。所以存储对象时不建议用String存储

18、Elasticsearch和solr的区别

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

19、单点登录实现过程

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

20、购物车实现过程

在这里插入图片描述
在这里插入图片描述

21、消息队列在项目中的应用

在这里插入图片描述

行锁
行锁的劣势:开销大;加锁慢;会出现死锁

行锁的优势:锁的粒度小,发生锁冲突的概率低;处理并发的能力强

加锁的方式:自动加锁。对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁;对于普通SELECT语句,InnoDB不会加任何锁;当然我们也可以显示的加锁:

共享锁:select * from tableName where … + lock in share more

排他锁:select * from tableName where … + for update

InnoDB和MyISAM的最大不同点有两个:一,InnoDB支持事务(transaction);二,默认采用行级锁。加锁可以保证事务的一致性,可谓是有人(锁)的地方,就有江湖(事务);我们先简单了解一下事务知识。


表锁
表锁的优势:开销小;加锁快;无死锁

表锁的劣势:锁粒度大,发生锁冲突的概率高,并发处理能力低

加锁的方式:自动加锁。查询操作(SELECT),会自动给涉及的所有表加读锁,更新操作(UPDATE、DELETE、INSERT),会自动给涉及的表加写锁。也可以显示加锁:

共享读锁:lock table tableName read;

独占写锁:lock table tableName write;

批量解锁:unlock tables;
详解链接:https://blog.csdn.net/xts5701046/article/details/81395958

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值