自己总结的一些合肥地区1-3年java面试题及答案

此篇文章是今年5月份面试一些公司问到的一些问题,在此与大家分享一下,话不多说进入正题。

  • java基础部分

1.JDK JVM JRE有什么区别?

JDK是针对Java开发员的产品,是整个Java的核心,包括了Java运行环境JRE、Java工具和Java基础类库。JRE是运行JAVA程序所必须的环境的集合,包含JVM标准实现及Java核心类库。JVM是Java虚拟机的缩写,是整个java实现跨平台的最核心的部分,能够运行以Java语言写作的软件程序。

2.java有几大特性?

java有4个基本特性分别是抽象、封装、继承、多态

3.string常用API列举?

常用的方法有length()计算字符串长度,equals()比较字符串,replace()替换,charAt()截取一个字符串,substring()截取字符串,indexOf()查找字符或者子串第一次出现的地方,concat()连接两个字符串,trim()去掉起始和结尾的空格,valueOf()转换为字符串等

4.如何删除字符串中指定的某个元素?

这是我写的一个测试方法,只是其中一种解决方法网上还有很多其他方法

public class test {
    public static void main(String[] args){
        String str = "abcde";
        String strafter= "";
        char delstr = 'a';
        for (int i=0;i<str.length();i++){
            if(str.charAt(i)!=delstr){
                strafter+=str.charAt(i);
            }
        }
        System.out.println(strafter);
    }
}

5.Arrylist和Linkedlist区别?

简单来说1. ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 2. 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。 3. 对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据 

6.list和map的几种遍历方式?

public static void main(String[] args) {  
   List<String> list=new ArrayList<String>();  
   list.add("123");  
   list.add("456");  
   list.add("789");  
   System.out.println("------经典的for循环-----");  
   for (int i = 0; i < list.size(); i++) {  
       System.out.println(list.get(i));  
   }  
   System.out.println("-------Iterate循环--------");  
   Iterator<String> iter=list.iterator();  
   while(iter.hasNext())  
   {  
       System.out.println(iter.next());  
   }  
   System.out.println("-------foreach循环---------");  
   for (String string : list) {  
     System.out.println(string);  
 }  
}  
//循环遍历map的方法  
public class MapF {  
 public static void main(String[] args) {  
  Map<String, Integer> tempMap = new HashMap<String, Integer>();  
  tempMap.put("a","12");  
  tempMap.put("b","34");  
  tempMap.put("c","56");  
  // JDK1.4中  
  // 遍历方法一 hashmap entrySet() 遍历  
  Iterator it = tempMap.entrySet().iterator();  
  while (it.hasNext()) {  
   Map.Entry entry = (Map.Entry) it.next();  
   Object key = entry.getKey();  
   Object value = entry.getValue();  
   System.out.println("key=" + key + " value=" + value);  
  }  
  System.out.println("");  
  // JDK1.5中,应用新特性For-Each循环  
  // 遍历方法二  
  for (Map.Entry<String, Integer> entry : tempMap.entrySet()) {  
   String key = entry.getKey().toString();  
   String value = entry.getValue().toString();  
   System.out.println("key=" + key + " value=" + value);  
  }  
  System.out.println("");  
  // 遍历方法三 hashmap keySet() 遍历  
  for (Iterator i = tempMap.keySet().iterator(); i.hasNext();) {  
   Object obj = i.next();  
   System.out.println(obj);// 循环输出key  
   System.out.println("key=" + obj + " value=" + tempMap.get(obj));  
  }  
  for (Iterator i = tempMap.values().iterator(); i.hasNext();) {  
   Object obj = i.next();  
   System.out.println(obj);// 循环输出value  
  }  
  // 遍历方法四 treemap keySet()遍历  
  for (Object o : tempMap.keySet()) {  
   System.out.println("key=" + o + " value=" + tempMap.get(o));  
  }  
  System.out.println("11111");  
  // java如何遍历Map <String, ArrayList> map = new HashMap <String,  
  // ArrayList>();  
  System.out.println("java  遍历Map <String, ArrayList> map = new HashMap<String, ArrayList>();");  
  Map<String, ArrayList> map = new HashMap<String, ArrayList>();  
  Set<String> keys = map.keySet();  
  Iterator<String> iterator = keys.iterator();  
  while (iterator.hasNext()) {  
   String key = iterator.next();  
   ArrayList arrayList = map.get(key);  
   for (Object o : arrayList) {  
    System.out.println(o);  
   }  
  }  
  Map<String, List> map = new HashMap<String, List>();  
  for (Map.Entry entry : map.entrySet()) {  
   String key = entry.getKey().toString();  
   List<String> list= (List) entry.getValue();  
   for (String value : list) {  
    System.out.println(key + "====" + value);  
   }  
  }  
 }  
}  

 

7.hashmap实现原理及与hashtable区别?

HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到bucket位置来储存值对象。当获取对象时,通过键对象的equals()方法找到正确的键值对,然后返回值对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会储存在链表的下一个节点中。 HashMap在每个链表节点中储存键值对对象。

当两个不同的键对象的hashcode相同时会发生什么? 它们会储存在同一个bucket位置的链表中。键对象的equals()方法用来找到键值对。

HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。

  1. HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。

  2. HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。

  3. 另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。

  4. 由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。

  5. HashMap不能保证随着时间的推移Map中的元素次序是不变的。

8.get与post请求区别?

简单总结一下1.get是从服务器上获取数据,post是向服务器传送数据。2. POST比GET安全,因为数据在地址栏上不可见。3.get方式提交的数据最多只能有1024字节,而post则没有此限制。4.GET使用URL或Cookie传参。而POST将数据放在BODY中。

9.接口和抽象类的区别?

1、一个类可以实现多个接口,但是却只能继承最多一个抽象类;

2、抽象类可以包含具体的方法,接口的所有方法都是抽象的;

3、抽象类可以声明和使用字段;接口则不能,但接口可以创静态的final常量;

4、接口的方法都是public的,抽象类的方法可以使public,private,protecte或者是默认的packag;

5、抽象类可以定义构造函数,但是接口不行。

10.mysql分页怎么做?

一般情况下,客户端通过传递 pageNo(页码)、pageSize(每页条数)两个参数去分页查询数据库中的数据,在数据量较小(元组百/千级)时使用 MySQL自带的 limit 来解决这个问题:

    收到客户端{pageNo:1,pagesize:10}
    select * from table limit (pageNo-1)*pageSize, pageSize;

   其实你答出limit和两个参数就可以了,问到oracle分页答出rownum关键字差不多了,如果数据量比较大这时我们就要考虑加索引了。

11.重定向和转发有什么区别?

重定向:以前的request中存放的变量全部失效,并进入一个新的request作用域。
             转发:以前的request中存放的变量不会失效,就像把两个页面拼到了一起。

通俗的说重定向用户请求变了而转发没变

  • java提升部分

1.简述Spring IOC AOP理解

IOC:Inversion of Control控制反转,也叫(Dependency Injection)依赖注入, dao接口的实现不再是业务逻辑层调用工厂类去获取,而是通过容器(spring)来自动的为我们的业务层设置Dao的实现类,这样整个过程就反过来,以前是我们业务层主动去获取dao,而现在是dao主动被设置到业务逻辑层中来了,这个也就是反转控制的由来。通过IOC,我们就可以在不修改任何代码的情况下,无缝地实现数据库的换库迁移

简单一点说:

IOC就是一个生产和管理bean的容器就行了,原来需要在调用类中new的东西,现在都是通过容器生成,同时,要是产生的是单例的bean,他还可以给管理bean的生命周期。

AOP:面向切面编程。(Aspect-Oriented Programming) 
AOP可以说是对OOP的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。实现AOP的技术。对于如权限认证、日志、事务等几乎业务功能都需要的功能,若采用OOP的设计则会产生大量的重复代码,不利于各模块的重用。Spring AOP采用的是动态代理,在运行期间对业务方法进行增强,所以不会生成新类,对于动态代理技术,Spring AOP提供了对JDK动态代理的支持以及CGLib的支持。

2.bean的生命周期

1.实例化bean对象(通过构造方法或者工厂方法)
             2.设置对象属性(setter等)(依赖注入)
             3.如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。
             4.如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身
             5.将Bean实例传递给Bean的前置处理器的postProcessBeforeInitialization(Object bean, String beanname)方法
             6.调用Bean的初始化方法
             7.将Bean实例传递给Bean的后置处理器的postProcessAfterInitialization(Object bean, String beanname)方法
             使用Bean
             8.容器关闭之前,调用Bean的销毁方法

两者的区别:
            1.JDK动态代理只能代理实现了接口的类,动态代理类的字节码在程序运行时由Java反射机制动态生成。
            2.Cglib是可以代理没有实现接口的类,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其             中方法实现增强,所以不能对final修饰的类进行代理。底层采用ASM实现。

3.Spring怎么管理事务(配置,事务的传播机制)

Spring的事务机制包括声明式事务和编程式事务。

编程式事务管理:Spring推荐使用TransactionTemplate,实际开发中使用声明式事务较多。

声明式事务管理:将我们从复杂的事务处理中解脱出来,获取连接,关闭连接、事务提交、回滚、异常处理等这些操作都不用我们处理了,Spring都会帮我们处理。

声明式事务管理使用了AOP面向切面编程实现的,本质就是在目标方法执行前后进行拦截。在目标方法执行前加入或创建一个事务,在执行方法执行后,根据实际情况选择提交或是回滚事务。

如何管理的:

Spring事务管理主要包括3个接口,Spring的事务主要是由他们三个共同完成的。

1)PlatformTransactionManager:事务管理器--主要用于平台相关事务的管理

 主要有三个方法:commit  事务提交;

      rollback  事务回滚;

      getTransaction  获取事务状态。

2)TransactionDefinition:事务定义信息--用来定义事务相关的属性,给事务管理器PlatformTransactionManager使用

这个接口有下面四个主要方法:

getIsolationLevel:获取隔离级别;

getPropagationBehavior:获取传播行为;

getTimeout:获取超时时间;

isReadOnly:是否只读(保存、更新、删除时属性变为false--可读写,查询时为true--只读)

事务管理器能够根据这个返回值进行优化,这些事务的配置信息,都可以通过配置文件进行配置。

3)TransactionStatus:事务具体运行状态--事务管理过程中,每个时间点事务的状态信息。

例如它的几个方法:

hasSavepoint():返回这个事务内部是否包含一个保存点,

isCompleted():返回该事务是否已完成,也就是说,是否已经提交或回滚

isNewTransaction():判断当前事务是否是一个新事务


声明式事务的优缺点:

优点

不需要在业务逻辑代码中编写事务相关代码,只需要在配置文件配置或使用注解(@Transaction),这种方式没有侵入性。

缺点

声明式事务的最细粒度作用于方法上,如果像代码块也有事务需求,只能变通下,将代码块变为方法。
 

4.简述Spring MVC流程

1.用户向服务器发出请求找到spring mvc的前端总控制器DispatcherServlet,并且通过DispatcherServlet来加载相关的配置文件信息。

2.DispatcherServlet接收到客户端请求,找到对应HandlerMapping,根据映射规则,找到对应的处理器(Handler)。

3.调用相应处理器中的处理方法,处理该请求后,会返回一个ModelAndView。

4.DispatcherServlet根据得到的ModelAndView中的视图对象,找到一个合适的ViewResolver(视图解析器),根据视图解析器的配置,DispatcherServlet将要显示的数据传给对应的视图,最后显示给用户

5.简述Spring MVC中用到哪些设计模式

1.工厂模式,这个很明显,在各种BeanFactory以及ApplicationContext创建中都用到了;
             2.模版模式,这个也很明显,在各种BeanFactory以及ApplicationContext实现中也都用到了;
             3.代理模式,在Aop实现中用到了JDK的动态代理;
             4.策略模式,第一个地方,加载资源文件的方式,使用了不同的方法,比如:ClassPathResourece,             FileSystemResource,ServletContextResource,UrlResource但他们都有共同的借口Resource;第二个地方就是在Aop的实现中,采用了两种不同的方式,JDK动态代理和CGLIB代理;
              5.单例模式,这个比如在创建bean的时候。

6.Spring MVC中如果出现两个相同的URL映射同一个控制器会怎样

启动时会报错org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:457)Context initialization failed
org.springframework.beans.factory.BeanCreationException:


7.controller根据什么判断返回的是json还是model and view

使用@ResponseBody 注解在方法上,返回的是JSON对象,那么展示的内容便是json字符串。

8.手写一个单例模式

/**
 * 饿汉式(程序启动的时候,就加载到内存中)
 * @author YUNATING
 *
 */
public class Singleton {
    
    private Singleton(){
    
    }
    private  static Singleton  singleton=new Singleton();
    
    private static Singleton getInstance() {
        return singleton;
    }

}

/**
 * 懒汉式(第一次调用该单例的时候,创建单例对象)
 * @author YUANTING
 *
 */
public class Singleton {
    
    private Singleton(){
    
    }
    private  static Singleton  singleton=null;//声明,不创建对象
    
    private static synchronized Singleton getInstance() {//懒汉式必须要加上synchronize同步锁关键字,否则线程不安全
        
        if(singleton==null) {//如果该单例没创建过,就创建该单例对象
            singleton=new Singleton();
        }
        return singleton;
    }

}
 

9.怎么保证接口安全

1.签名:根据用户名或者用户id,结合用户的ip或者设备号,生成一个token。在请求后台,后台获取http的head中的token,校验是否合法(和数据库或者redis中记录的是否一致,在登录或者初始化的时候,存入数据库/redis)

2.加密:客户端和服务器都保存一个秘钥,每次传输都加密,服务端根据秘钥解密。

3.第三方支持:比如spring security-oauth 

10.创建线程的几种方式

1)继承Thread类创建线程

2)实现Runnable接口创建线程

3)使用Callable和Future创建线程

4)使用线程池例如用Executor框架

11.wait和sleep的区别

 sleep是Thread类的方法,wait是Object类中定义的方法

 sleep()方法可以在任何地方使用

 wait()方法只能在synchronized方法或synchronized块中使用

最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

12.怎么保证多个线程按照顺序执行

join()

13.知道哪些线程安全手法

在Java中可以有很多方法来保证线程安全,比如使用同步方法、同步块,使用原子类(atomic concurrent classes),实现并发锁,使用volatile关键字,使用不变类和线程安全类。

总结一下,一个被volatile声明的变量主要有以下两种特性保证保证线程安全。1.有序性2.可见性

在满足以下两个条件的情况下,volatile就能保证变量的线程安全问题:

              1.  运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值。

               2. 变量不需要与其他状态变量共同参与不变约束。

14.线程池一些配置信息

corePoolSize:核心线程数

核心线程会一直存活,及时没有任务需要执行

当线程数小于核心线程数时,即使有线程空闲,线程池也会优先创建新线程处理

设置allowCoreThreadTimeout=true(默认false)时,核心线程会超时关闭

queueCapacity:任务队列容量(阻塞队列)

当核心线程数达到最大时,新任务会放在队列中排队等待执行

maxPoolSize:最大线程数

当线程数>=corePoolSize,且任务队列已满时。线程池会创建新线程来处理任务

当线程数=maxPoolSize,且任务队列已满时,线程池会拒绝处理任务而抛出异常

keepAliveTime:线程空闲时间

当线程空闲时间达到keepAliveTime时,线程会退出,直到线程数量=corePoolSize

如果allowCoreThreadTimeout=true,则会直到线程数量=0

allowCoreThreadTimeout:允许核心线程超时

rejectedExecutionHandler:任务拒绝处理器

15.如何配置tomcat的JVM内存大小

Linux下修改JVM内存大小:

要添加在tomcat 的bin 下catalina.sh 里,位置cygwin=false前 。注意引号要带上,红色的为新添加的.

# OS specific support. $var _must_ be set to either true or false.
JAVA_OPTS="-Xms256m -Xmx512m -Xss1024K -XX:PermSize=128m -XX:MaxPermSize=256m"
cygwin=false

windows下修改JVM内存大小:

情况一:解压版本的Tomcat, 要通过startup.bat启动tomcat才能加载配置

要添加在tomcat 的bin 下catalina.bat 里

rem Guess CATALINA_HOME if not defined
set CURRENT_DIR=%cd%后面添加,红色的为新添加的.

set JAVA_OPTS=-Xms256m -Xmx512m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m -Djava.awt.headless=true

情况二:安装版的Tomcat下没有catalina.bat

windows服务执行的是bin/tomcat.exe.他读取注册表中的值,而不是catalina.bat的设置.

修改注册表HKEY_LOCAL_MACHINE/SOFTWARE/Apache Software Foundation/Tomcat Service Manager/Tomcat5/Parameters/JavaOptions
原值为
-Dcatalina.home="C:/ApacheGroup/Tomcat 5.0"
-Djava.endorsed.dirs="C:/ApacheGroup/Tomcat 5.0/common/endorsed"
-Xrs

加入 -Xms300m -Xmx350m 
重起tomcat服务,设置生效

16.如何确保一个集合不被修改

 Collections.unmodifiableList(List)
             Collections.unmodifiableMap(Map)
             Collections.unmodifiableSet(Set)
以上返回的集合对象都是不可修改的,调用修改方法会抛出异常UnsupportedOperationException

17.tcp 为什么要三次握手,两次不行吗?为什么?

首先,我们要知道TCP是全双工的,即客户端在给服务器端发送信息的同时,服务器端也可以给客户端发送信息。而半双工的意思是A可以给B发,B也可以给A发,但是A在给B发的时候,B不能给A发,即不同时,为半双工。 单工为只能A给B发,B不能给A发; 或者是只能B给A发,不能A给B发。

  我们假设A和B是通信的双方。我理解的握手实际上就是通信,发一次信息就是进行一次握手。

第一次握手: A给B打电话说,你可以听到我说话吗?

第二次握手: B收到了A的信息,然后对A说: 我可以听得到你说话啊,你能听得到我说话吗?  

第三次握手: A收到了B的信息,然后说可以的,我要给你发信息啦!

  在三次握手之后,A和B都能确定这么一件事: 我说的话,你能听到; 你说的话,我也能听到。 这样,就可以开始正常通信了。

  注意: HTTP是基于TCP协议的,所以每次都是客户端发送请求,服务器应答,但是TCP还可以给其他应用层提供服务,即可能A、B在建立链接之后,谁都可能先开始通信。

  如果两次,那么B无法确定B的信息A是否能收到,所以如果B先说话,可能后面的A都收不到,会出现问题 。

  如果四次,那么就造成了浪费,因为在三次结束之后,就已经可以保证A可以给B发信息,A可以收到B的信息; B可以给A发信息,B可以收到A的信息。

  • 数据库部分

1.数据库连接池的一些配置信息

具体数值根据业务场景来设这里我们举C3P0为例<!-- Spring配置c3p0数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="driverClass" value="${jdbc.driverClassName}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <!--连接池中保留的最大连接数。Default: 15 --> <property name="maxPoolSize" value="100" /> <!--连接池中保留的最小连接数。--> <property name="minPoolSize" value="1" /> <!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 --> <property name="initialPoolSize" value="10" /> <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 --> <property name="maxIdleTime" value="30" /> <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 --> <property name="acquireIncrement" value="5" /> <!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。Default: 0--> <property name="maxStatements" value="0" /> <!--每60秒检查所有连接池中的空闲连接。Default: 0 --> <property name="idleConnectionTestPeriod" value="60" /> <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 --> <property name="acquireRetryAttempts" value="30" /> <!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。Default: false--> <property name="breakAfterAcquireFailure" value="true" /> <!--因性能消耗大请只在需要的时候使用它。Default: false --> <property name="testConnectionOnCheckout"  value="false" /> </bean>
 

2.mysql几种存储引擎

(1)、InnoDB 存储引擎
InnoDB 是事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键,InnoDB 是默认的 MySQL
引擎。
              (2)、MyISAM 存储引擎
MyISAM 基于 ISAM 存储引擎,并对其进行扩展。它是在 Web、数据仓储和其他应用环境下最常使用的存储引擎
之一。MyISAM 拥有较高的插入、查询速度,但不支持事物。
              (3)、MEMORY 存储引擎
MEMORY 存储引擎将表中的数据存储到内存中,未查询和引用其他表数据提供快速访问。
              (4)、NDB 存储引擎
DB 存储引擎是一个集群存储引擎,类似于 Oracle 的 RAC,但它是 Share Nothing 的架构,因此能提供更高级
别的高可用性和可扩展性。NDB 的特点是数据全部放在内存中,因此通过主键查找非常快。
关于 NDB,有一个问题需要注意,它的连接(join)操作是在 MySQL 数据库层完成,不是在存储引擎层完成,这
意味着,复杂的 join 操作需要巨大的网络开销,查询速度会很慢。
             (5)、Memory (Heap) 存储引擎
Memory 存储引擎(之前称为 Heap)将表中数据存放在内存中,如果数据库重启或崩溃,数据丢失,因此它非
常适合存储临时数据。

(6)、Archive 存储引擎
正如其名称所示,Archive 非常适合存储归档数据,如日志信息。它只支持 INSERT 和 SELECT 操作,其设计的主
要目的是提供高速的插入和压缩功能。
             (7)、Federated 存储引擎
Federated 存储引擎不存放数据,它至少指向一台远程 MySQL 数据库服务器上的表,非常类似于 Oracle 的透明
网关。
             (8)、Maria 存储引擎
Maria 存储引擎是新开发的引擎,其设计目标是用来取代原有的 MyISAM 存储引擎,从而成为 MySQL 默认
的存储引擎。
上述引擎中,InnoDB 是事务安全的存储引擎,设计上借鉴了很多 Oracle 的架构思想,一般而言,在 OLTP
应用中,InnoDB 应该作为核心应用表的首先存储引擎。

3.事务的特性及隔离等级

四大特性

⑴ 原子性(Atomicity)

  原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

⑵ 一致性(Consistency)

  一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

  拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。

⑶ 隔离性(Isolation)

  隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

  即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。

  关于事务的隔离性数据库提供了多种隔离级别,稍后会介绍到。

⑷ 持久性(Durability)

  持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

现在来看看MySQL数据库为我们提供的四种隔离级别:

  ① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。

  ② Repeatable read (可重复读):可避免脏读、不可重复读的发生。

  ③ Read committed (读已提交):可避免脏读的发生。

  ④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。

4.事务的应用场景

要满足上述的4大特性比如说商城买商品  银行汇款 简单来说A+ B-这种

5.常用的SQL优化
            

1. 尽量使用列名(Oracle9i之后, *和列名一样)
   在业务密集的SQL当中尽量不采用IN操作符,用EXISTS 方案代替。

2、模糊查询like
关键词%yue%,由于yue前面用到了“%”,因此该查询必然走全表扫描,除非必要,否则不要在关键词前加%,

3 二者都能使用尽量使用where (与having比较)
where 先过滤(数据就少了)在分组  

4: 理论上,尽量使用多表连接(join)查询(避免子查询)(有时面试官还会问到为什么连接查询比子查询效率高,因为子查询会建临时表查询过后还会销毁所以时间会更长)
 

6.根据什么建立索引

1.主键自动建立唯一索引;

2.频繁作为查询条件的字段应该创建索引;

3.查询中与其他表有关联的字段,例如外键关系;

4.频繁更新的字段不适合创建索引,因为每次更新不单单是更新记录,还会更新索引,保存索引文件;

5.where条件里用不到的字段,不创建索引;

6.高并发的情况下一般选择复合索引;

7.查询中排序的字段创建索引将大大提高排序的速度(索引就是排序加快速查找);

8.查询中统计或者分组的字段;

9.表记录太少,不需要创建索引;

10.经常增删改的表;

11.数据重复且分布平均的字段,因此为经常查询的和经常排序的字段建立索引。注意某些数据包含大量重复数据,因此他建立索引就没有太大的效果,例如性别字段,只有男女,不适合建立索引。

7.左连接和右链接是什么概念

左连接是已左边表中的数据为基准,若左表有数据右表没有数据,则显示左表中的数据右表中的数据显示为空。

右连接则相反。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值