电脑做ppt一般下载哪个网站好,哈尔滨网站设计定制,鞍山做百度网站一年多少钱,wordpress 添加分页myibatis执行过程 1读取MyBatis的配置文件。
mybatis-config.xml为MyBatis的全局配置文件#xff0c;用于配置数据库连接信息。
2加载映射文件。映射文件即SQL映射文件#xff0c;该文件中配置了操作数据库的SQL语句#xff0c;需要在MyBatis配置文件mybatis-config.xml中…myibatis执行过程 1读取MyBatis的配置文件。
mybatis-config.xml为MyBatis的全局配置文件用于配置数据库连接信息。
2加载映射文件。映射文件即SQL映射文件该文件中配置了操作数据库的SQL语句需要在MyBatis配置文件mybatis-config.xml中加载。mybatis-config.xml 文件可以加载多个映射文件每个文件对应数据库中的一张表。
3构造会话工厂。
通过MyBatis的环境配置信息构建会话工厂SqlSessionFactory。
4 创建会话对象。
由会话工厂创建SqlSession对象该对象中包含了执行SQL语句的所有方法。
5 Executor执行器。
MyBatis底层定义了一个Executor接口来操作数据库它将根据SqlSession传递的参数动态地生成需要执行的SQL语句同时负责查询缓存的维护。
6MappedStatement对象。
在Executor接口的执行方法中有一个MappedStatement类型的参数该参数是对映射信息的封装用于存储要映射的SQL语句的id、参数等信息。
7 输入参数映射。
输入参数类型可以是Map、List等集合类型也可以是基本数据类型和POJO类型。输入参数映射过程类似于JDBC对preparedStatement对象设置参数的过程。
8 输出结果映射。
输出结果类型可以是Map、List等集合类型也可以是基本数据类型和POJO类型。输出结果映射过程类似于JDBC对结果集的解析过程。
mybatis的优缺点有哪些
1、Mybait的优点
1简单易学容易上手相比于Hibernate 基于SQL编程 2JDBC相比减少了50%以上的代码量消除了JDBC大量冗余的代码不需要手动开关连接 3很好的与各种数据库兼容因为MyBatis使用JDBC来连接数据库所以只要JDBC支持的数据库MyBatis都支持而JDBC提供了可扩展性所以只要这个数据库有针对Java的jar包就可以就可以与MyBatis兼容开发人员不需要考虑数据库的差异性。 4提供了很多第三方插件分页插件 / 逆向工程 5能够与Spring很好的集成 6MyBatis相当灵活不会对应用程序或者数据库的现有设计强加任何影响SQL写在XML里从程序代码中彻底分离解除sql与程序代码的耦合便于统一管理和优化并可重用。 7提供XML标签支持编写动态SQL语句。 8提供映射标签支持对象与数据库的ORM字段关系映射。 9提供对象关系映射标签支持对象关系组建维护。 2、MyBatis框架的缺点
1SQL语句的编写工作量较大尤其是字段多、关联表多时更是如此对开发人员编写SQL语句的功底有一定要求。 2SQL语句依赖于数据库导致数据库移植性差不能随意更换数据库。
mybatis和hibernate有什么区别
Hibernate的优点
1、hibernate是全自动hibernate完全可以通过对象关系模型实现对数据库的操作拥有完整的JavaBean对象与数据库的映射结构来自动生成sql。
2、功能强大数据库无关性好O/R映射能力强需要写的代码很少开发速度很快。
3、有更好的二级缓存机制可以使用第三方缓存。
4、数据库移植性良好。
5、hibernate拥有完整的日志系统hibernate日志系统非常健全涉及广泛包括sql记录、关系异常、优化警告、缓存提示、脏数据警告等
Hibernate的缺点
1、学习门槛高精通门槛更高程序员如何设计O/R映射在性能和对象模型之间如何取得平衡以及怎样用好Hibernate方面需要的经验和能力都很强才行
2、hibernate的sql很多都是自动生成的无法直接维护sql虽然有hql查询但功能还是不及sql强大见到报表等变态需求时hql查询要虚也就是说hql查询是有局限的hibernate虽然也支持原生sql查询但开发模式上却与orm不同需要转换思维因此使用上有些不方便。总之写sql的灵活度上hibernate不及mybatis。
Mybatis的优点
1、易于上手和掌握提供了数据库查询的自动对象绑定功能而且延续了很好的SQL使用经验对于没有那么高的对象模型要求的项目来说相当完美。
2、sql写在xml里便于统一管理和优化 解除sql与程序代码的耦合。
3、提供映射标签支持对象与数据库的orm字段关系映射
4、 提供对象关系映射标签支持对象关系组建维护
5、提供xml标签支持编写动态sql。
6、速度相对于Hibernate的速度较快
Mybatis的缺点
1、关联表多时字段多的时候sql工作量很大。
2、sql依赖于数据库导致数据库移植性差。
3、由于xml里标签id必须唯一导致DAO中方法不支持方法重载。
4、对象关系映射标签和字段映射标签仅仅是对映射关系的描述具体实现仍然依赖于sql。
5、DAO层过于简单对象组装的工作量较大。
6、不支持级联更新、级联删除。
7、Mybatis的日志除了基本记录功能外其它功能薄弱很多。
8、编写动态sql时,不方便调试尤其逻辑复杂时。
9、提供的写动态sql的xml标签功能简单编写动态sql仍然受限且可读性低。
mybatis中#{}和${}的区别是什么
a、#{}是预编译处理${}是字符串替换。 b、Mybatis 在处理#{}时会将 sql 中的#{}替换为?号调用 PreparedStatement 的 set 方法来赋值 c、Mybatis 在处理${}时就是把${}替换成变量的值。 d、使用#{}可以有效的防止 SQL 注入提高系统安全性
简述一下mybatis插件运行原理及开发流程插件四大天王
mybatis只支持针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这四种接口的插件mybatis使用jdk的动态代理为需要拦截的接口生成代理对象以实现接口方法拦截功能每当执行这四种接口对象的方法时就会进入拦截方法具体就是InvocationHandler的invoke方法拦截那些你指定需要拦截的方法。
编写插件实现Mybatis的Interceptor接口并复写intercept方法啊然后给插件编写注解指定要拦截哪一个接口的哪些方法在配置文件中配置编写的插件即可。
Intercepts({Signature(type StatementHandler.class,method parameterize,args Statement.class)})
插件开发流程 创建自定义拦截器类实现org.apache.ibatis.plugin.Interceptor接口并重写其中的intercept()和plugin()方法。intercept()方法用于定义自定义逻辑plugin()方法用于生成代理对象。 在拦截器类上使用Intercepts注解寻找需要拦截的方法。 在MyBatis的配置文件通常是mybatis-config.xml中配置自定义拦截器。 创建插件类继承org.apache.ibatis.plugin.PluginAdapter类并实现其中的setProperties()方法。 在插件类上使用Signature注解指定要拦截的方法签名。 编写一个类实现org.apache.ibatis.session.Configuration接口重写其中的addInterceptor()方法在方法中添加自定义插件。 在MyBatis的配置文件中使用configuration标签的settings子标签并指定使用自定义的配置类。 调用MyBatis的API进行数据库操作时插件将被自动执行。
mybatis的mapper没有实现类
在 MyBatis 中Mapper 接口可以不需要对应的实现类因为 MyBatis 会自动为 Mapper 接口生成代理对象并实现接口中定义的方法。这种方式称为 Mapper 接口的动态代理。
当 Mapper 接口没有对应的实现类时MyBatis 在运行时会动态生成一个代理对象该代理对象会拦截接口方法的调用并根据接口方法的定义将对应的 SQL 语句进行执行。这样就实现了 Mapper 接口与 SQL 语句的绑定。
在 Mapper 接口中通常会使用注解或 XML 文件来定义 SQL 语句。例如使用注解方式定义 SQL 语句的 Mapper 接口示例
java public interface UserMapper { Select(SELECT * FROM users WHERE id #{id}) User selectUserById(Long id); }
而使用 XML 文件定义 SQL 语句的 Mapper 接口示例
java public interface UserMapper { User selectUserById(Long id); }
xml !-- UserMapper.xml -- mapper namespacecom.example.UserMapper select idselectUserById resultTypecom.example.User SELECT * FROM users WHERE id #{id} /select /mapper
当应用程序调用 Mapper 接口中的方法时MyBatis 会根据方法的定义注解或 XML 文件中的配置来执行对应的 SQL 语句将查询结果映射为 Java 对象并返回给调用方。
总结来说即使 Mapper 接口没有对应的实现类MyBatis 也能通过动态代理的方式实现接口与 SQL 语句的绑定使开发人员可以方便地以接口的方式来操作数据库提高了开发效率和代码的可维护性。
MyBatis 与 Spring 框架整合
在将 MyBatis 与 Spring 框架整合时需要配置 Spring 的 ApplicationContext并将 MyBatis 的 SqlSessionFactory 注入到 Spring 的容器中以便让 Spring 管理 MyBatis 的 SqlSessionFactory并能够进行事务管理、异常处理等操作。下面是将 MyBatis 与 Spring 整合的一般步骤
1. **配置 MyBatis 的 SqlSessionFactoryBean** 在 Spring 的配置文件中配置 MyBatis 的 SqlSessionFactoryBean用于创建 MyBatis 的 SqlSessionFactory 实例并配置数据源、Mapper 接口扫描等信息。
xml bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBean property namedataSource refdataSource / property namemapperLocations valueclasspath:com/example/mappers/*.xml / /bean
2. **配置 MyBatis 的 MapperScannerConfigurer** 使用 MapperScannerConfigurer 配置自动扫描 Mapper 接口并将其注册为 Spring 的 Bean。
xml bean classorg.mybatis.spring.mapper.MapperScannerConfigurer property namebasePackage valuecom.example.mappers / /bean
3. **配置事务管理器和动态代理**配置事务管理器如 DataSourceTransactionManager以及 MyBatis 的 Mapper Bean 动态代理。
xml bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManager property namedataSource refdataSource / /bean
bean classorg.mybatis.spring.mapper.MapperFactoryBean property namesqlSessionFactory refsqlSessionFactory / property namemapperInterface valuecom.example.UserMapper / /bean
4. **在业务逻辑中使用 Mapper 接口** 在业务逻辑的 Spring Bean 中注入 Mapper 接口然后就可以通过 Mapper 接口来执行 SQL 操作。
java Autowired private UserMapper userMapper;
5. **配置数据源和其他必要的 Bean** 还需要配置数据源、事务管理器等其它必要的 Bean用于 MyBatis 与数据库的交互和事务管理。
通过以上步骤将 MyBatis 与 Spring 整合后就可以在 Spring 的应用程序中方便地使用 MyBatis 来操作数据库实现数据访问层的功能。整合的过程主要是通过配置 Spring 的配置文件来管理 MyBatis 的相关 Bean并利用 Spring 的依赖注入来获取需要的组件从而实现 MyBatis 与 Spring 的无缝整合。
MyBatis 缓存
MyBatis 是一个流行的持久层框架用于对数据库进行操作。MyBatis 提供了一级缓存和二级缓存来优化数据库访问提高系统性能。
一级缓存 一级缓存是 MyBatis 中默认开启的缓存它指的是 SqlSession 级别的缓存。当查询完数据后数据将会保存在 SqlSession 的缓存中后续对同一条数据的查询将不会再访问数据库而是直接从缓存中获取。一级缓存的作用域是当前 SqlSession在同一个 SqlSession 中进行的多次查询可以共享一级缓存。
二级缓存 二级缓存是 MyBatis 的全局缓存它作用于 SqlSessionFactory 级别可以被同一个数据库的不同 SqlSession 所共享。这意味着当不同的 SqlSession 执行相同的 SQL 查询时可以从二级缓存中获取数据而不必再次访问数据库。需要注意的是二级缓存是跨 SqlSession 的如果在一个 SqlSession 中更新了数据会清空二级缓存中与该数据相关的数据保证缓存的一致性。
启用二级缓存的步骤包括 在 MyBatis 的配置文件中开启二级缓存 settingssetting namecacheEnabled valuetrue/
/settings 针对需要使用二级缓存的映射文件添加 cache/ 标签 mapper namespacecom.example.UserMappercache/!-- 其他映射配置 --
/mapper
需要注意的是当配置了二级缓存后需要在需要共享缓存的实体类中通过 cache/ 标签明确指定是否开启二级缓存因为默认情况下是关闭的。并且需要确保相关的实体类实现了 Serializable 接口。因为二级缓存默认使用 Java 的序列化机制进行对象的序列化和反序列化。
总的来说一级缓存和二级缓存在 MyBatis 中是用来提升查询性能的重要机制。一级缓存作用于 SqlSession 级别适用于短生命周期的对象而二级缓存作用于 SqlSessionFactory 级别适用于长生命周期的对象可以在不同 SqlSession 之间共享缓存但需要注意数据的一致性。 Mybatis是如何进行分页的分页插件的原理是什么 Mybatis使用RowBounds对象进行分页它是针对ResultSet结果集执行的内存分页而非物理分页可以在sql内直接书写带有物理分页的参数来完成物理分页功能也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口实现自定义插件在插件的拦截方法内拦截待执行的sql然后重写sql根据dialect方言添加对应的物理分页语句和物理分页参数。
举例select * from student拦截sql后重写为select t.* from (select * from student) t limit 0, 10 MyBatis编程步骤是什么样的 1、 创建SqlSessionFactory
2、 通过SqlSessionFactory创建SqlSession
3、 通过sqlsession执行数据库操作
4、 调用session.commit()提交事务
5、 调用session.close()关闭会话
Mybatis都有哪些Executor执行器它们之间的区别是什么 Mybatis有三种基本的Executor执行器SimpleExecutor、ReuseExecutor、BatchExecutor。
SimpleExecutor每执行一次update或select就开启一个Statement对象用完立刻关闭Statement对象。
ReuseExecutor执行update或select以sql作为key查找Statement对象存在就使用不存在就创建用完后不关闭Statement对象而是放置于MapString, Statement内供下一次使用。简言之就是重复使用Statement对象。
BatchExecutor执行update没有selectJDBC批处理不支持select将所有sql都添加到批处理中addBatch()等待统一执行executeBatch()它缓存了多个Statement对象每个Statement对象都是addBatch()完毕后等待逐一执行executeBatch()批处理。与JDBC批处理相同。
作用范围Executor的这些特点都严格限制在SqlSession生命周期范围内。 模糊查询like语句该怎么写 1’%${question}%’ 可能引起SQL注入不推荐
2%#{question}% 注意因为#{…}解析成sql语句时候会在变量外侧自动加单引号’ 所以这里 % 需要使用双引号 不能使用单引号 ’ 不然会查不到任何结果。
3CONCAT(’%’,#{question},’%’) 使用CONCAT()函数推荐
4使用bind标签
select idlistUserLikeUsername resultTypecom.jourwon.pojo.User bind namepattern value% username % / select id,sex,age,username,password from person where username LIKE #{pattern} /select 在mapper中如何传递多个参数 方法1顺序传参法
public User selectUser(String name, int deptId);
select idselectUser resultMapUserResultMap select * from user where user_name #{0} and dept_id #{1} /select #{}里面的数字代表传入参数的顺序。
这种方法不建议使用sql层表达不直观且一旦顺序调整容易出错。
方法2Param注解传参法
public User selectUser(Param(userName) String name, int Param(deptId) deptId);
select idselectUser resultMapUserResultMap select * from user where user_name #{userName} and dept_id #{deptId} /select #{}里面的名称对应的是注解Param括号里面修饰的名称。
这种方法在参数不多的情况还是比较直观的推荐使用。
方法3Map传参法
public User selectUser(MapString, Object params);
select idselectUser parameterTypejava.util.Map resultMapUserResultMap select * from user where user_name #{userName} and dept_id #{deptId} /select #{}里面的名称对应的是Map里面的key名称。
这种方法适合传递多个参数且参数易变能灵活传递的情况。
方法4Java Bean传参法
public User selectUser(User user);
select idselectUser parameterTypecom.jourwon.pojo.User resultMapUserResultMap select * from user where user_name #{userName} and dept_id #{deptId} /select #{}里面的名称对应的是User类里面的成员属性。
这种方法直观需要建一个实体类扩展不容易需要加属性但代码可读性强业务逻辑处理方便推荐使用。
Mybatis如何执行批量操作 使用foreach标签
foreach的主要用在构建in条件中它可以在SQL语句中进行迭代一个集合。foreach标签的属性主要有itemindexcollectionopenseparatorclose。
item 表示集合中每一个元素进行迭代时的别名随便起的变量名 index 指定一个名字用于表示在迭代过程中每次迭代到的位置不常用 open 表示该语句以什么开始常用“(” separator表示在每次进行迭代之间以什么符号作为分隔符常用“,” close 表示以什么结束常用“)”。 在使用foreach的时候最关键的也是最容易出错的就是collection属性该属性是必须指定的但是在不同情况下该属性的值是不一样的主要有一下3种情况
如果传入的是单参数且参数类型是一个List的时候collection属性值为list 如果传入的是单参数且参数类型是一个array数组的时候collection的属性值为array 如果传入的参数是多个的时候我们就需要把它们封装成一个Map了当然单参数也可以封装成map实际上如果你在传入参数的时候在MyBatis里面也是会把它封装成一个Map的 map的key就是参数名所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key 具体用法如下
!-- 批量保存(foreach插入多条数据两种方法) int addEmpsBatch(Param(emps) ListEmployee emps); -- !-- MySQL下批量保存可以foreach遍历 mysql支持values(),(),()语法 -- //推荐使用 insert idaddEmpsBatch INSERT INTO emp(ename,gender,email,did) VALUES foreach collectionemps itememp separator, (#{emp.eName},#{emp.gender},#{emp.email},#{emp.dept.id}) /foreach /insert !-- 这种方式需要数据库连接属性allowMutiQueriestrue的支持 如jdbc.urljdbc:mysql://localhost:3306/mybatis?allowMultiQueriestrue -- insert idaddEmpsBatch foreach collectionemps itememp separator; INSERT INTO emp(ename,gender,email,did) VALUES(#{emp.eName},#{emp.gender},#{emp.email},#{emp.dept.id}) /foreach /insert 在 MyBatis 中进行一对一和一对多的关联查询 在 MyBatis 中实现一对一和一对多的关联查询通常有以下几种方式
### 一对一关联查询的实现方式 1. **嵌套查询Nested Queries** 在父查询中通过嵌套查询子查询来获取关联对象的信息。 2. **嵌套结果Nested Results** 在 SQL 查询语句中通过使用嵌套 Select 语句实现一对一关联查询。 3. **嵌套映射Nested Mapping** 通过在 ResultMap 中定义嵌套的 ResultMap 来实现一对一关联查询。
下面是一种常见的嵌套查询方式的操作步骤
1. 在 SQL Mapper XML 文件中配置
!-- 查询订单信息并关联查询用户信息 --
select idselectOrderWithUser resultMaporderUserResultMapSELECT o.*, u.id as user_id, u.username as user_username, u.email as user_emailFROM orders oINNER JOIN users u ON o.user_id u.idWHERE o.id #{orderId}
/select!-- 定义 ResultMap --
resultMap idorderUserResultMap typeOrderid propertyid columnid /association propertyuser resultMapuserResultMap /
/resultMapresultMap iduserResultMap typeUserid propertyid columnuser_id/result propertyusername columnuser_username /result propertyemail columnuser_email /
/resultMap 2. 在 Mapper 接口中定义方法 Order selectOrderWithUser(Long orderId); 3. 在 Service 层调用 Mapper 中定义的方法 Order order orderMapper.selectOrderWithUser(orderId); 一对多关联查询的实现方式 1. **嵌套查询** 使用多条 SQL 查询语句来获取一对多关联的数据。 2. **嵌套结果** 在 SQL 查询语句中使用 Join 等方式将一对多关联的数据合并在查询结果中。 3. **嵌套映射** 通过在 ResultMap 中定义 Collection 来实现一对多关联查询。
下面是一种常见的嵌套查询方式的操作步骤
1. 在 SQL Mapper XML 文件中配置
!-- 查询部门信息并关联查询所有员工信息 --
select idselectDepartmentWithEmployees resultMapdepartmentEmployeesResultMapSELECT d.id as department_id, d.name as department_name,e.id as employee_id, e.name as employee_name, e.email as employee_emailFROM departments dLEFT JOIN employees e ON d.id e.department_idWHERE d.id #{departmentId}
/select!-- 定义 ResultMap --
resultMap iddepartmentEmployeesResultMap typeDepartmentid propertyid columndepartment_id /result propertyname columndepartment_name /collection propertyemployees ofTypeEmployeeid propertyid columnemployee_id/result propertyname columnemployee_name/result propertyemail columnemployee_email//collection
/resultMap 2. 在 Mapper 接口中定义方法 Department selectDepartmentWithEmployees(Long departmentId); 3. 在 Service 层调用 Mapper 中定义的方法 Department department departmentMapper.selectDepartmentWithEmployees(departmentId); 通过以上方式可以实现在 MyBatis 中进行一对一和一对多的关联查询具体的方式可以根据实际业务需求和数据结构选择最适合的方式进行操作。 Select * 的缺点
1. 不需要的列会增加数据传输时间和网络开销 用“SELECT * ”数据库需要解析更多的对象、字段、权限、属性等相关内容在 SQL 语句复杂硬解析较多的情况下会对数据库造成沉重的负担。 增大网络开销* 有时会误带上如log、IconMD5之类的无用且大文本字段数据传输size会几何增涨。如果DB和应用程序不在同一台机器这种开销非常明显 即使 mysql 服务器和客户端是在同一台机器上使用的协议还是 tcp通信也是需要额外的时间。
2. 对于无用的大字段如 varchar、blob、text会增加 io 操作
准确来说长度超过 728 字节的时候会先把超出的数据序列化到另外一个地方因此读取这条记录会增加一次 io 操作。MySQL InnoDB
3. 失去MySQL优化器“覆盖索引”策略优化的可能性
SELECT * 杜绝了覆盖索引的可能性而基于MySQL优化器的“覆盖索引”策略又是速度极快效率极高业界极为推荐的查询优化方式
select count(*)和select count(1)的区别
1、 一般情况下Select Count (*)和Select Count(1)两着返回结果是一样的
2、 假如表沒有主键(Primary key), 那么count(1)比count(*)快
3、 如果有主键的話那主键作为count的条件时候count(主键)最快
4、 如果你的表只有一个字段的话那count(*)就是最快的
5、count(*) 跟 count(1) 的结果一样都包括对NULL的统计而count(column) 是不包括NULL的统计
左连接 left Join 右连接内连接
在 MySQL 中左连接LEFT JOIN、右连接RIGHT JOIN和内连接INNER JOIN是 SQL 中常用的连接类型它们的定义与区别如下
### 1. 左连接LEFT JOIN
- 左连接是从左表左边返回所有匹配左表的行并返回右表中与左表匹配的行如果右表中没有匹配的行则显示为 NULL 值。 - 语法SELECT * FROM 左表 LEFT JOIN 右表 ON 左表.列 右表.列; - 左表中的所有行都会显示在结果集中右表中没有匹配的行会被填充为 NULL 值。
### 2. 右连接RIGHT JOIN
- 右连接是从右表右边返回所有匹配右表的行并返回左表中与右表匹配的行如果左表中没有匹配的行则显示为 NULL 值。 - 语法SELECT * FROM 左表 RIGHT JOIN 右表 ON 左表.列 右表.列; - 右表中的所有行都会显示在结果集中左表中没有匹配的行会被填充为 NULL 值。
### 3. 内连接INNER JOIN
- 内连接是返回匹配两个表中行的行并丢弃不匹配的行即两个表中连接条件不符合的行会被过滤掉。 - 语法SELECT * FROM 表1 INNER JOIN 表2 ON 表1.列 表2.列; - 只返回两个表中连接条件符合的行不匹配的行不会显示在结果集中。
### 区别总结 - 左连接返回左表中所有行以及与左表匹配的右表行右连接返回右表中所有行以及与右表匹配的左表行内连接只返回两个表中连接条件符合的行。 - 三种连接方式都可以通过 ON 子句中指定连接条件根据实际需求选择合适的连接方式来获取所需数据。
在实际应用中根据具体业务需求和数据关系选择合适的连接方式以获取正确的结果集。
数据库的五大范式
具体内容如下
第一范式无重复列
即在一行中的每一列仅有唯一的值并且具有原子性
第二范式任意一个字段都只依赖表中的同一字段或者说属性完全依赖于主键
即非主键列的活动必须完全依赖整个主键主键必须有唯一性的元素
第三范式属性不能传递依赖于主属性或者说属性不依赖其他非主属性
即非主键列互不依赖
第四范式禁止主键列和非主键列一对多关系不受约束 第五范式将表分割成尽可能小的块为了排序在表中所有的冗余
MySql的三种日志及作用
这三种日志在 MySQL 数据库中扮演着关键的角色它们分别支撑着数据库的事务持久性、数据一致性和可靠性。 Redo Log重做日志 作用记录事务对数据页所做的修改在事务提交前就将相关的 Redo log 记录持久化到磁盘。这样在事务提交后即使数据页还未写入磁盘数据库也能通过 Redo log 进行数据的恢复保证了事务的持久性。 数据一致性和可靠性重做日志的存在保证了即使在数据库崩溃或断电的情况下提交的事务对数据的修改也不会丢失从而确保了数据的一致性和可靠性。 Undo Log回滚日志 作用记录事务执行过程中对数据的旧值支持事务的回滚和读取操作的多版本并发控制。当事务执行中需要回滚或读取之前的版本时可以通过 Undo log 进行数据的恢复操作。 数据一致性和可靠性Undo log 保证了事务的原子性和一致性即使事务执行过程中出现错误或需要回滚也能确保数据的一致性和可靠性。 Binlog二进制日志 作用记录了所有的数据库修改操作包括对表的插入、更新、删除等操作以及对数据库结构的变更。Binlog 主要用于数据库的主从复制、数据恢复、数据迁移等场景。 数据一致性和可靠性通过 Binlog数据库可以在分布式系统中实现主从复制确保不同节点之间的数据一致性和可靠性同时通过恢复 Binlog 也能实现对数据库的数据恢复和数据迁移保证了数据的可靠性和一致性。
综合来看通过 Redo log 的持久化、Undo log 的回滚支持和 Binlog 的记录和传播MySQL 服务器保证了数据的一致性和可靠性。这些日志机制都是数据库引擎和服务器核心的组成部分确保了数据库的 ACID 特性即原子性、一致性、隔离性和持久性。
redo log和binlog区别 redo log是属于innoDB层面binlog属于MySQL Server层面的这样在数据库用别的存储引擎时可以达到一致性的要求。 redo log是物理日志记录该数据页更新的内容binlog是逻辑日志记录的是这个更新语句的原始逻辑 redo log是循环写日志空间大小固定binlog是追加写是指一份写到一定大小的时候会更换下一个文件不会覆盖。 binlog可以作为恢复数据使用主从复制搭建redo log作为异常宕机或者介质故障后的数据恢复使用。
索引的基本原理
1、为什么要有索引? 一般的应用系统读写比例在10:1左右而且插入操作和一般的更新操作很少出现性能问题在生产环境中我们遇到最多的也是最容易出问题的还是一些复杂的查询操作因此对查询语句的优化显然是重中之重。说起加速查询就不得不提到索引了。 2、什么是索引 索引在MySQL中也叫是一种“键”是存储引擎用于快速找到记录的一种数据结构。索引对于良好的性能 非常关键尤其是当表中的数据量越来越大时索引对于性能的影响愈发重要。 索引优化应该是对查询性能优化最有效的手段了。索引能够轻易将查询性能提高好几个数量级。 索引相当于字典的音序表如果要查某个字如果不使用音序表则需要从几百页中逐页去查。
3、索引的原理
索引的目的在于提高查询效率与我们查阅图书所用的目录是一个道理先定位到章然后定位到该章下的一个小节然后找到页数。相似的例子还有查字典查火车车次飞机航班等
本质都是通过不断地缩小想要获取数据的范围来筛选出最终想要的结果同时把随机的事件变成顺序的事件也就是说有了这种索引机制我们可以总是用同一种查找方式来锁定数据。
数据库也是一样但显然要复杂的多因为不仅面临着等值查询还有范围查询(、、between、in)、模糊查询(like)、并集查询(or)等等。数据库应该选择怎么样的方式来应对所有的问题呢我们回想字典的例子能不能把数据分成段然后分段查询呢最简单的如果1000条数据1到100分成第一段101到200分成第二段201到300分成第三段…这样查第250条数据只要找第三段就可以了一下子去除了90%的无效数据。但如果是1千万的记录呢分成几段比较好按照搜索树的模型其平均复杂度是lgN具有不错的查询性能。但这里我们忽略了一个关键的问题复杂度模型是基于每次相同的操作成本来考虑的。而数据库实现比较复杂一方面数据是保存在磁盘上的另外一方面为了提高性能每次又可以把部分数据读入内存来计算因为我们知道访问磁盘的成本大概是访问内存的十万倍左右所以简单的搜索树难以满足复杂的应用场景。
4、索引的数据结构
MySQL主要用到两种结构B Tree索引和Hash索引 Inodb存储引擎 默认是 BTree索引 Memory 存储引擎 默认 Hash索引 MySQL中只有Memory(Memory表只存在内存中断电会消失适用于临时表)存储引擎显示支持Hash索引是Memory表的默认索引类型尽管Memory表也可以使用BTree索引。Hash索引把数据以hash形式组织起来因此当查找某一条记录的时候速度非常快。但是因为hash结构每个键只对应一个值而且是散列的方式分布。所以它并不支持范围查找和排序等功能。 BTree是mysql使用最频繁的一个索引数据结构是InnoDB和MyISAM存储引擎模式的索引类型。相对Hash索引BTree在查找单条记录的速度比不上Hash索引但是因为更适合排序等操作所以它更受欢迎。毕竟不可能只对数据库进行单条记录的操作。 对比 hash类型的索引查询单条快范围查询慢 btree类型的索引b树层数越多数据量指数级增长我们就用它因为innodb默认支持它 B 树索引结构
在 MySQL 中B 树B Tree是一种常用的索引结构用于加速数据库表的数据查找操作。下面详细讲解 MySQL 中的 B 树索引结构以及选择它的原因
### 1. B 树索引结构
- **结构特点** - B 树是一种平衡多路搜索树具有树形结构每个节点可以包含多个子节点。 - 每个非叶子节点存储索引字段和指向子节点的指针叶子节点存储索引字段和指向数据行的指针。 - 叶子节点按顺序连接形成一个有序链表方便范围查询操作。
- **查找过程** - 从根节点开始根据节点中的索引值进行比较沿着合适的路径向下查找直到找到叶子节点。 - 在叶子节点中进行精确查找或范围查找找到对应的数据行。
### 2. 为什么选择 B 树索引结构
- **高效的检索性能** B 树是一种高效的索引结构其查询的时间复杂度为 O(logN)可以快速定位到指定数据行适用于大数据量数据库表的索引。
- **有序性和范围查询** B 树的叶子节点形成有序链表适合范围查询操作能够快速定位到指定范围的数据行。
- **支持高效的插入和删除操作** B 树的平衡性和节点分裂合并策略可以保持树的平衡保证高效的插入和删除操作。
- **适合磁盘存储** B 树的节点通常比较大可以减少磁盘 I/O 次数适合磁盘存储的数据库系统。
- **支持索引顺序遍历** B 树的叶子节点形成有序链表可以支持索引的顺序遍历提高查询性能。
- **适合范围查询和排序** B 树的有序性和范围查询优势使其适合在 MySQL 数据库中用于支持范围查询、排序操作。
综上所述MySQL 选择 B 树作为索引结构的原因是因为它能够提供高效的检索性能、有序性以支持范围查询、适合磁盘存储、支持高效的插入和删除操作等特点能够满足数据库系统对索引结构的需求提高数据库表的查询性能和效率。
索引的最左匹配原则
最左匹配原则是指在复合索引中MySQL会按照索引的最左列开始匹配查询条件然后逐渐向右匹配。只有当查询条件中连续的列满足了索引的最左前缀时索引才能被充分利用。以下是一些例子来说明最左匹配原则 假设有一个复合索引 (column1, column2, column3)。 有效的查询条件示例WHERE column1 A 无效的查询条件示例WHERE column2 B因为没有匹配到索引的最左列 column1 假设有一个复合索引 (column1, column2)。 有效的查询条件示例WHERE column1 A 有效的查询条件示例WHERE column1 A AND column2 B 无效的查询条件示例WHERE column2 B因为没有匹配到索引的最左列 column1 假设有一个复合索引 (column1, column2)。 有效的查询条件示例WHERE column1 A 无效的查询条件示例WHERE column2 B因为没有匹配到索引的最左列 column1 最左前缀匹配原则非常重要的原则mysql会一直向右匹配直到遇到范围查询(、、between、like)就停止匹配比如a 1 and b 2 and c 3 and d 4 如果建立(a,b,c,d)顺序的索引d是用不到索引的如果建立(a,b,d,c)的索引则都可以用到a,b,d的顺序可以任意调整。 和in可以乱序比如a 1 and b 2 and c 3 建立(a,b,c)索引可以任意顺序mysql的查询优化器会帮你优化成索引可以识别的形式
总结起来最左匹配原则适用于以下情况 查询条件从索引的最左列开始连续向右匹配索引列。 查询条件中的列满足了索引的最左前缀。
如果查询条件不符合以上两个条件那么最左匹配原则将失效MySQL将无法充分利用复合索引。
在设计和优化索引时了解最左匹配原则是很有帮助的。它可以帮助你合理地选择索引列的顺序以提高查询性能和索引的利用率。
mysql聚簇和非聚簇索引的区别是什么
mysql的索引类型跟存储引擎是相关的innodb存储引擎数据文件跟索引文件全部放在ibd文件中而myisam的数据文件放在myd文件中索引放在myi文件中其实区分聚簇索引和非聚簇索引非常简单只要判断数据跟索引是否存储在一起就可以了。
innodb存储引擎在进行数据插入的时候数据必须要跟索引放在一起如果有主键就使用主键没有主键就使用唯一键没有唯一键就使用6字节的rowid因此跟数据绑定在一起的就是聚簇索引而为了避免数据冗余存储其他的索引的叶子节点中存储的都是聚簇索引的key值因此innodb中既有聚簇索引也有非聚簇索引而myisam中只有非聚簇索引。
mysql索引结构有哪些各自的优劣是什么
索引的数据结构和具体存储引擎的实现有关mysql中使用较多的索引有hash索引B树索引innodb的索引实现为B树memory存储引擎为hash索引。
B树是一个平衡的多叉树从根节点到每个叶子节点的高度差值不超过1而且同层级的二节点间有指针相关连接在B树上的常规检索从根节点到叶子节点的搜索效率基本相当不会出现大幅波动而且基于索引的顺序扫描时也可以利用双向指针快速左右移动效率非常高。因为B树索引被广泛应用于数据库、文件系统等场景。
哈希索引就是采用一定的哈希算法把键值换算成新的哈希值检索时不需要类似B树那样从根节点到叶子节点逐级查找只需一次哈希算法即可立刻定位到相应的位置速度非常快。
如果是等值查询那么哈希索引明显有绝对优势因为只需要经过一次算法即可找到相应的键值前提是键值都是唯一的。如果键值不是唯一的就需要先找到该键所在位置然后再根据链表往后扫描知道找到对应的数据
如果是范围查询检索这时候哈徐索引就毫无用武之地了因为原先是有序的键值经过哈希算法后有可能变成不连续的了就没办法再利用索引完成范围查询检索
哈希所有也没办法利用索引完成排序以及like这样的部分模糊查询
哈希索引也不支持多列联合索引的最左匹配规则
B树索引的关键字检索效率比较平均不像B树那样波动大在有大量重复键值情况下哈希索引的效率也是极低的因此存在哈希碰撞问题。
索引的设计原则有哪些
在数据库中创建索引是提高查询效率和性能的重要手段之一。以下是一些创建索引的原则 选择合适的列选择那些经常用于查询和连接的列来创建索引。通常包括经常出现在WHERE、JOIN、ORDER BY和GROUP BY子句中的列。 避免过度索引不要为每个列都创建索引因为索引的维护和存储会带来额外的开销。过多的索引不仅会占用磁盘空间还可能导致索引失效、降低写操作的性能等问题。 考虑列的选择性选择具有较高选择性不重复值较多的列来创建索引这样可以减少索引的大小和搜索的区间。 考虑查询的频率和重要性根据查询的频率和重要性来选择创建索引的列。如果某个查询非常频繁且对性能要求较高那么为该查询常用的列创建索引是很有必要的。 综合考虑查询和更新的平衡索引会提高查询的速度但会降低更新操作的速度。因此在创建索引时需要综合考虑查询和更新的平衡选择适当的索引策略。 考虑数据量和存储空间索引会占用额外的存储空间因此在创建索引时需要考虑数据量的大小。对于较大的表和数据量庞大的表需要谨慎选择创建索引的列以避免过度的存储开销。 定期维护和更新索引索引的性能和效果是需要定期维护和更新的。当表的数据发生变化时如插入、更新或删除操作需要及时更新索引以保持索引的有效性。 使用复合索引对于经常同时查询多个列的情况可以考虑创建复合索引即包含多个列的联合索引。复合索引可以提高查询效率并且可以减少索引的数量。
除了以上原则外创建索引还需要根据具体的数据库系统和查询需求做进一步的优化和调整。在进行索引设计时需要综合考虑数据库结构、查询模式、数据量等因素以达到提高查询性能的目的。 在进行索引设计的时候应该保证索引字段占用的空间越小越好这只是一个大的方向还有一些细节点需要注意下
1、适合索引的列是出现在where字句中的列或者连接子句中指定的列
2、基数较小的表索引效果差没必要创建索引
3、在选择索引列的时候越短越好可以指定某些列的一部分没必要用全部字段的值
4、不要给表中的每一个字段都创建索引并不是索引越多越好
5、定义有外键的数据列一定要创建索引
6、更新频繁的字段不要有索引
7、创建索引的列不要过多可以创建组合索引但是组合索引的列的个数不建议太多
8、大文本、大对象不要创建索引 索引失效的十大原因
索引失效的场景
1、不满足最左匹配原则
2、索引列上有计算 如where id12
3、索引列上使用了函数 如where SUBSTR(name,1,2)17
4、字段类型不同如本来是数字类型结果加上了引号变成了字符串
5、like 左边加上了%号6、列对比两个列在where后面进行比较
7、使用or如果使用or前面和后面的列都要加上索引才会生效
8、not in和not exists如果主键索引会走索引其他不会
9、! 慎重使用基本会走全表Extral中有using where全表扫描
10、排序列和联合索引顺序不一致
11、排序列包含非一个索引的列
https://www.cnblogs.com/wushaopei/p/12283647.html 什么是回表查询
通俗的讲就是如果索引的列在 select 所需获得的列中因为在 mysql 中索引是根据索引列的值进行排序的所以索引节点中存在该列中的部分值或者根据一次索引查询就能获得记录就不需要回表如果 select 所需获得列中有大量的非索引列索引就需要到表中找到相应的列的信息这就叫回表。
回表查询先定位主键值再定位行记录它的性能较扫一遍索引树更低。
使用聚集索引主键或第一个唯一索引就不会回表普通索引就会回表
什么是覆盖索引***
通常开发人员会根据查询的where条件来创建合适的索引但是优秀的索引设计应该考虑到整个查询。其实mysql可以使用索引来直接获取列的数据。如果索引的叶子节点包含了要查询的数据那么就不用回表查询了也就是说这种索引包含亦称覆盖所有需要查询的字段的值我们称这种索引为覆盖索引。
1、索引项通常比记录要小所以MySQL访问更少的数据。
2、索引都按值得大小存储相对于随机访问记录需要更少的I/O。
3、数据引擎能更好的缓存索引比如MyISAM只缓存索引。
4、覆盖索引对InnoDB尤其有用因为InnoDB使用聚集索引组织数据如果二级索引包含查询所需的数据就不再需要在聚集索引中查找了。
限制
1、覆盖索引也并不适用于任意的索引类型索引必须存储列的值。
2、Hash和full-text索引不存储值因此MySQL只能使用BTree。
3、不同的存储引擎实现覆盖索引都是不同的并不是所有的存储引擎都支持覆盖索引。
4、如果要使用覆盖索引一定要注意SELECT列表值取出需要的列不可以SELECT * 因为如果将所有字段一起做索引会导致索引文件过大查询性能下降。
索引下推
如果没有索引下推优化或称ICP优化当进行索引查询时首先根据索引来查找记录然后再根据where条件来过滤记录在支持ICP优化后MySQL会在取出索引的同时判断是否可以进行where条件过滤再进行索引查询也就是说提前执行where的部分过滤操作在某些场景下可以大大减少回表次数从而提升整体性能。 mysql锁的类型有哪些
基于锁的属性分类共享锁、排他锁。
基于锁的粒度分类行级锁innodb 、表级锁 innodb 、myisam、页级锁 innodb引擎、记录锁、间隙锁、临键锁。
基于锁的状态分类意向共享锁、意向排它锁。
共享锁share lock 共享锁又称读锁简称 S 锁当一个事务为数据加上读锁之后其他事务只能对该数据加读锁而不能对数据加写锁直到所有的读锁释放之后其他事务才能对其进行加持写锁。共享锁的特性主要是为了支持并发的读取数据读取数据的时候不支持修改避免出现重复读的问题。
排他锁exclusive lock排他锁又称写锁简称 X 锁当一个事务为数据加上写锁时其他请求将不能再为数据加任何锁直到该锁释放之后其他事务才能对数据进行加锁。排他锁的目的是在数据修改时候不允许其他人同时修改也不允许其他人读取避免了出现脏数据和脏读的问题。
表锁table lock表锁是指上锁的时候锁住的是整个表当下一个事务访问该表的时候必须等前一个事务释放了锁才能进行对表进行访问特点粒度大加锁简单容易冲突
行锁行锁是指上锁的时候锁住的是表的某一行或多行记录其他事务访问同一张表时只有被锁住的记录不能访问其他的记录可正常访问特点粒度小加锁比表锁麻烦不容易冲突相比表锁支持的并发要高
记录锁Record lock:记录锁也属于行锁中的一种只不过记录锁的范围只是表中的某一条记录记录锁是说事务在加锁后锁住的只是表的某一条记录加了记录锁之后数据可以避免数据在查询的时候被修改的重复读问题也避免了在修改的事务未提交前被其他事务读取的脏读问题
页锁页级锁是 MysQL 中锁定粒度介于行级锁和表级锁中间的一种锁表级锁速度快但冲突多行级冲突少但速度慢。所以取了折衷的页级一次锁定相邻的一组记录。特点开销和加锁时间界于表锁和行锁之间会出现死锁锁定粒度界于表锁和行锁之间并发度一般。
间隙锁是属于行锁的一种间隙锁是在事务加锁后其锁住的是表记录的某一个区间当表的相邻ID之间出现空隙则会形成一个区间遵循左开右闭原则。范围查询并且查询未命中记录查询条件必须命中索引、间隙锁只会出现在REPEATABLE_READ重复读的事务级别中。
临键锁Next-Key lock)也属于行锁的一种并且它是INNODB的行锁默认算法总结来说它就是记录锁和间隙锁的组合临键锁会把查询出来的记录锁住同时也会把该范围查询内的所有间隙空间也会锁住再之它会把相邻的下一个区间也会锁住。
mysql执行计划怎么看
在 MySQL 中可以通过使用 EXPLAIN 关键字来查看 SQL 语句的执行计划帮助优化查询性能。下面是使用 EXPLAIN 查看 MySQL 执行计划的方法
### 1. 基本语法
sql EXPLAIN SELECT * FROM your_table WHERE your_condition; 2. 实际操作步骤 a. 执行查询前加上 EXPLAIN 关键字
sql EXPLAIN SELECT * FROM your_table WHERE your_condition;
b. 查看执行计划结果
执行以上 SQL 语句后会返回一张表格其中包含了关于查询执行的各种重要信息例如查询的优化方式、表的读取顺序、使用的索引、行数估算等。
c. 解读执行计划信息
在执行计划结果中可以注意以下一些重要的字段信息
- **id** 查询的顺序如果是子查询会有多个执行顺序。 - **select_type** 查询类型如 SIMPLE、PRIMARY、DERIVED、SUBQUERY 等。 - **table** 显示查询操作涉及的表。 - **type** 表示 MySQL 在表中找到所需行的方式常见的类型有 const、eq_ref、ref、range、index、all 等通常从最好到最差的顺序排列。 - **key** 显示 MySQL 决定使用哪个索引来优化查询。 - **rows** 评估在找到所需行之前要检查的行数。 - **Extra** 包含关于查询执行的额外信息可能包括使用了索引、临时表等信息。 3. 根据执行计划优化 SQL
通过查看执行计划可以了解 MySQL 数据库是如何执行你的查询的并可以根据执行计划的信息进行 SQL 语句的调优例如添加合适的索引、优化表结构、改变查询方式等以提高查询性能和效率。
通过上述方法你可以使用 EXPLAIN 关键字来查看 MySQL 的执行计划帮助分析和优化查询语句的执行效率。 事务的基本特性是什么
事务四大特征原子性一致性隔离性和持久性。 原子性Atomicity 一个原子事务要么完整执行要么干脆不执行。这意味着工作单元中的每项任务都必须正确执行。如果有任一任务执行失败则整个工作单元或事务就会被终止。即此前对数据所作的任何修改都将被撤销。如果所有任务都被成功执行事务就会被提交即对数据所作的修改将会是永久性的。 一致性Consistency 一致性代表了底层数据存储的完整性。它必须由事务系统和应用开发人员共同来保证。事务系统通过保证事务的原子性隔离性和持久性来满足这一要求; 应用开发人员则需要保证数据库有适当的约束(主键引用完整性等)并且工作单元中所实现的业务逻辑不会导致数据的不一致(即数据预期所表达的现实业务情况不相一致)。例如在一次转账过程中从某一账户中扣除的金额必须与另一账户中存入的金额相等。支付宝账号100 你读到余额要取有人向你转100 但是事物没提交这时候你读到的余额应该是100而不是200 这种就是一致性 隔离性Isolation 隔离性意味着事务必须在不干扰其他进程或事务的前提下独立执行。换言之在事务或工作单元执行完毕之前其所访问的数据不能受系统其他部分的影响。 持久性Durability 持久性表示在某个事务的执行过程中对数据所作的所有改动都必须在事务成功结束前保存至某种物理存储设备。这样可以保证所作的修改在任何系统瘫痪时不至于丢失。
MySQL的隔离级别有哪些
MySQL定义了四种隔离级别包括一些具体规则用于限定事务内外哪些改变是可见的哪些改变是不可见的。低级别的隔离一般支持更高的并发处理并且拥有更低的系统开销。
READ UNCOMMITTED 读取未提交内容 在这个隔离级别所有事务都可以“看到”未提交事务的执行结果。在这种级别上可能会产生很多问题除非用户真的知道自己在做什么并有很好的理由选择这样做。本隔离级别很少用于实际应用因为它的性能也不必其他性能好多少而别的级别还有其他更多的优点。读取未提交数据也被称为“脏读”
READ COMMITTED 读取提交内容 大多数数据库系统的默认隔离级别但是不是MySQL的默认隔离级别满足了隔离的早先简单定义一个事务开始时只能“看见”已经提交事务所做的改变一个事务从开始到提交前所做的任何数据改变都是不可见的除非已经提交。这种隔离级别也支持所谓的“不可重复读”。这意味着用户运行同一个语句两次看到的结果是不同的。
REPEATABLE READ 可重复读 MySQL数据库默认的隔离级别。该级别解决了READ UNCOMMITTED隔离级别导致的问题。它保证同一事务的多个实例在并发读取事务时会“看到同样的”数据行。不过这会导致另外一个棘手问题“幻读”。InnoDB和Falcon存储引擎通过多版本并发控制机制解决了幻读问题。
SERIALIZABLE 可串行化 该级别是最高级别的隔离级。它通过强制事务排序使之不可能相互冲突从而解决幻读问题。简而言之SERIALIZABLE是在每个读的数据行上加锁。在这个级别可能导致大量的超时Timeout和锁竞争Lock Contention现象实际应用中很少使用到这个级别但如果用户的应用为了数据的稳定性需要强制减少并发的话也可以选择这种隔离级。 一级封锁协议。事务T在修改数据R之前必须先对其加X 锁 直到事务结束才释放。可防止丢失修改 二级封锁协议。一级封锁协议加上事务T在读取数据R之前先对其加S锁读完后即可释放S锁。可防止丢失修改还可防止读“脏”数据 三级封锁协议。一级封锁协议加上事务T在读取数据R之前先对其加S锁直到事务结束才释放。可防止丢失修改、防止读“脏”数据与防止数据(不可)重复读
两段锁协议。可串行化的。可能发生死锁 脏读
脏读是指一个事务读取了未提交事务执行过程中的数据。 当一个事务的操作正在多次修改数据而在事务还未提交的时候另外一个并发事务来读取了数据就会导致读取到的数据并非是最终持久化之后的数据这个数据就是脏读的数据。 不可重复读
不可重复读是指对于数据库中的某个数据一个事务执行过程中多次查询返回不同查询结果这就是在事务执行过程中数据被其他事务提交修改了。 不可重复读同脏读的区别在于脏读是一个事务读取了另一未完成的事务执行过程中的数据而不可重复读是一个事务执行过程中另一事务提交并修改了当前事务正在读取的数据。 虚读(幻读)
幻读是事务非独立执行时发生的一种现象例如事务T1批量对一个表中某一列列值为1的数据修改为2的变更但是在这时事务T2对这张表插入了一条列值为1的数据并完成提交。此时如果事务T1查看刚刚完成操作的数据发现还有一条列值为1的数据没有进行修改而这条数据其实是T2刚刚提交插入的这就是幻读。 幻读和不可重复读都是读取了另一条已经提交的事务这点同脏读不同所不同的是不可重复读查询的都是同一个数据项而幻读针对的是一批数据整体比如数据的个数。
怎么处理MySQL的慢查询
处理 MySQL 的慢查询可以采取以下几种方法 使用索引优化慢查询通常是由于缺乏或不正确使用索引导致的。通过分析慢查询的执行计划确定应该创建哪些索引来加速查询。可以使用 EXPLAIN 或 EXPLAIN ANALYZE 命令来查看查询的执行计划并使用 CREATE INDEX 命令创建适当的索引。 优化查询语句优化查询语句的编写可以显著提升查询性能。避免使用全表扫描和不必要的连接操作尽量简化查询条件并使用合适的查询语句如使用 INNER JOIN 替代 WHERE 子句中的子查询。 - 确保编写高效的 SQL 查询语句避免不必要的查询、使用 SELECT *、多余的子查询等。 - 尽量避免在 WHERE 子句中对字段进行函数操作会影响索引的使用。 - 使用合适的 JOIN 操作避免笛卡尔积Cartesian Product和不必要的连接。 - 限制返回结果集的大小避免一次性获取过多数据。 调整服务器参数通过适当设置 MySQL 服务器的参数可以提升数据库的性能。例如增加缓冲区大小如 innodb_buffer_pool_size、优化查询缓存如 query_cache_size和调整并发连接数等。 切分大表如果查询的表非常大可以考虑将大表切分为更小的表在查询时只查询所需的分片表可以减轻单个查询的负载提高查询速度。 定期优化和维护数据库定期对数据库进行优化和维护可以提升整体性能。包括定期进行表优化、碎片整理、数据归档和备份等操作以确保数据库的健康状态。 监控和记录慢查询及时发现和记录慢查询是优化的起点。通过开启慢查询日志slow query log来记录慢查询语句然后根据日志分析找出消耗时间较长的查询优化这些查询可以提高整体性能。 使用缓存对于一些频繁查询的数据可以考虑使用缓存技术如使用 Redis、Memcached 等缓存服务器缓存查询结果减少对数据库的访问次数提高响应速度。 使用数据库连接池使用数据库连接池可以减少数据库连接的开销提高并发性能。连接池会管理数据库连接的获取和释放合理配置连接池参数可以提高数据库的性能和稳定性。
通过以上方法可以逐步优化和改进数据库的慢查询问题提升数据库的性能和响应速度。需要根据具体的业务场景和数据库配置来选择和调整优化策略。
ACID是靠什么保证的
原子性由undolog日志来保证它记录了需要回滚的日志信息事务回滚时撤销已经执行成功的sql
一致性是由其他三大特性保证程序代码要保证业务上的一致性
隔离性是由MVCC来保证
持久性由redolog来保证mysql修改数据的时候会在redolog中记录一份日志数据就算数据没有保存成功只要日志保存成功了数据仍然不会丢失
什么是MVCC
1、MVCC
MVCC全称Multi-Version Concurrency Control即多版本并发控制。MVCC是一种并发控制的方法一般在数据库管理系统中实现对数据库的并发访问在编程语言中实现事务内存。 MVCC在MySQL InnoDB中的实现主要是为了提高数据库并发性能用更好的方式去处理读写冲突做到即使有读写冲突时也能做到不加锁非阻塞并发读。
2、当前读
像select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)这些操作都是一种当前读为什么叫当前读就是它读取的是记录的最新版本读取时还要保证其他并发事务不能修改当前记录会对读取的记录进行加锁。
3、快照读提高数据库的并发查询能力
像不加锁的select操作就是快照读即不加锁的非阻塞读快照读的前提是隔离级别不是串行级别串行级别下的快照读会退化成当前读之所以出现快照读的情况是基于提高并发性能的考虑快照读的实现是基于多版本并发控制即MVCC,可以认为MVCC是行锁的一个变种但它在很多情况下避免了加锁操作降低了开销既然是基于多版本即快照读可能读到的并不一定是数据的最新版本而有可能是之前的历史版本
4、当前读、快照读、MVCC关系
MVCC多版本并发控制指的是维持一个数据的多个版本使得读写操作没有冲突快照读是MySQL为实现MVCC的一个非阻塞读功能。MVCC模块在MySQL中的具体实现是由三个隐式字段undo日志、read view三个组件来实现的。
MVCC解决的问题是什么
数据库并发场景有三种分别为
1、读读不存在任何问题也不需要并发控制
2、读写有线程安全问题可能会造成事务隔离性问题可能遇到脏读、幻读、不可重复读
3、写写有线程安全问题可能存在更新丢失问题
MVCC是一种用来解决读写冲突的无锁并发控制也就是为事务分配单项增长的时间戳为每个修改保存一个版本版本与事务时间戳关联读操作只读该事务开始前的数据库的快照所以MVCC可以为数据库解决一下问题
1、在并发读写数据库时可以做到在读操作时不用阻塞写操作写操作也不用阻塞读操作提高了数据库并发读写的性能
2、解决脏读、幻读、不可重复读等事务隔离问题但是不能解决更新丢失问题
MVCC实现原理是什么 MVCCMulti-Version Concurrency Control是一种数据库并发控制技术常用于实现事务的隔离性保证事务之间的并发执行。MVCC 的实现原理主要通过版本控制来实现多个事务并发执行而不会相互影响常见于像 MySQL、PostgreSQL 等数据库系统中。
### MVCC 的实现原理如下
1. **版本控制** 每次对数据库的数据进行更新时并不直接修改原始数据而是创建新的版本或称为快照来保存被修改的数据。这样每个事务在读取数据时都会读取到一个版本的数据而不会受到其他事务同时修改数据的影响。
2. **事务版本号** 每个事务有一个唯一的事务版本号用来标识该事务可以读取的数据版本。事务在读取数据时会根据自己的事务版本号来确定所读取数据的版本从而实现事务之间的隔离性。
3. **数据行的版本信息** 每行数据都会包含版本信息通常有两种方式来实现 - 一种是在数据行中添加版本号字段用来记录数据的版本信息 - 另一种是使用时间戳记录数据被修改的时间。
4. **读取版本判断** 当事务读取数据时系统会根据事务的版本号和数据的版本信息来判断是否可以读取该数据一般有以下几种情况 - 如果数据的版本号在事务开始之前则可以读取 - 如果数据的版本号在事务开始之后但是数据的更新事务未提交则根据事务隔离级别确定是否可以读取。
5. **写操作处理** 当事务对数据进行更新时系统会创建一个新的版本来保存修改后的数据同时保留原始数据的版本。其他事务在读取数据时可以根据版本控制机制来读取到合适的数据版本。
通过 MVCC 技术数据库系统可以实现高并发性和事务隔离性同时保证数据的一致性。不同的数据库系统可能会有不同的实现细节但 MVCC 的核心思想是基于版本控制来实现并发控制。 RC读提交内容、RR可重复读级别下的InnoDB快照读有什么不同
因为Read View生成时机的不同从而造成RC、RR级别下快照读的结果的不同
1、在RR级别下的某个事务的对某条记录的第一次快照读会创建一个快照即Read View,将当前系统活跃的其他事务记录起来此后在调用快照读的时候还是使用的是同一个Read View,所以只要当前事务在其他事务提交更新之前使用过快照读那么之后的快照读使用的都是同一个Read View,所以对之后的修改不可见
2、在RR级别下快照读生成Read View时Read View会记录此时所有其他活动和事务的快照这些事务的修改对于当前事务都是不可见的而早于Read View创建的事务所做的修改均是可见
3、在RC级别下事务中每次快照读都会新生成一个快照和Read View,这就是我们在RC级别下的事务中可以看到别的事务提交的更新的原因。
总结在RC隔离级别下是每个快照读都会生成并获取最新的Read View,而在RR隔离级别下则是同一个事务中的第一个快照读才会创建Read View之后的快照读获取的都是同一个Read View.
什么是mysql的主从复制
MySQL 主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点。MySQL 默认采用异步复制方式这样从节点不用一直访问主服务器来更新自己的数据数据的更新可以在远程连接上进行从节点可以复制主数据库中的所有数据库或者特定的数据库或者特定的表。
mysql为什么需要主从同步
1、在业务复杂的系统中有这么一个情景有一句sql语句需要锁表导致暂时不能使用读的服务那么就很影响运行中的业务使用主从复制让主库负责写从库负责读这样即使主库出现了锁表的情景通过读从库也可以保证业务的正常运作。
2、做数据的热备
3、架构的扩展。业务量越来越大I/O访问频率过高单机无法满足此时做多库的存储降低磁盘I/O访问的频率提高单个机器的I/O性能。 mysql复制原理是什么
1master服务器将数据的改变记录二进制binlog日志当master上的数据发生改变时则将其改变写入二进制日志中
2slave服务器会在一定时间间隔内对master二进制日志进行探测其是否发生改变如果发生改变则开始一个I/OThread请求master二进制事件
3同时主节点为每个I/O线程启动一个dump线程用于向其发送二进制事件并保存至从节点本地的中继日志中从节点将启动SQL线程从中继日志中读取二进制日志在本地重放使得其数据和主节点的保持一致最后I/OThread和SQLThread将进入睡眠状态等待下一次被唤醒。
也就是说 从库会生成两个线程,一个I/O线程,一个SQL线程; I/O线程会去请求主库的binlog,并将得到的binlog写到本地的relay-log(中继日志)文件中; 主库会生成一个log dump线程,用来给从库I/O线程传binlog; SQL线程,会读取relay log文件中的日志,并解析成sql语句逐一执行;
注意
1--master将操作语句记录到binlog日志中然后授予slave远程连接的权限master一定要开启binlog二进制日志功能通常为了数据安全考虑slave也开启binlog功能
。 2--slave开启两个线程IO线程和SQL线程。其中IO线程负责读取master的binlog内容到中继日志relay log里SQL线程负责从relay log日志里读出binlog内容并更新到slave的数据库里这样就能保证slave数据和master数据保持一致了。
3--Mysql复制至少需要两个Mysql的服务当然Mysql服务可以分布在不同的服务器上也可以在一台服务器上启动多个服务。
4--Mysql复制最好确保master和slave服务器上的Mysql版本相同如果不能满足版本一致那么要保证master主节点的版本低于slave从节点的版本 5--master和slave两节点间时间需同步 具体步骤
1、从库通过手工执行change master to 语句连接主库提供了连接的用户一切条件user 、password、port、ip并且让从库知道二进制日志的起点位置file名 position 号 start slave
2、从库的IO线程和主库的dump线程建立连接。
3、从库根据change master to 语句提供的file名和position号IO线程向主库发起binlog的请求。
4、主库dump线程根据从库的请求将本地binlog以events的方式发给从库IO线程。
5、从库IO线程接收binlog events并存放到本地relay-log中传送过来的信息会记录到master.info中
6、从库SQL线程应用relay-log并且把应用过的记录到relay-log.info中默认情况下已经应用过的relay 会自动被清理purge
简述Myisam和Innodb的区别 MyISAM和InnoDB是MySQL数据库中常见的两种存储引擎它们在性能、功能和特性上有一些区别。以下是它们的主要区别 事务支持 MyISAM不支持事务而InnoDB支持事务。事务是一系列数据库操作的逻辑单元可以保证数据的一致性和完整性。对于需要严格事务支持的应用如高并发的OLTP联机事务处理系统InnoDB更加适合。 并发控制 MyISAM使用表级锁定即当一个线程对表执行写操作时其他线程无法对该表进行写操作但可以进行读操作。而InnoDB使用行级锁定允许并发事务读写不同的行提供更好的并发性能。 数据完整性 MyISAM不提供外键约束也不支持事务的回滚和崩溃恢复功能。而InnoDB支持外键约束可以保证数据的一致性和完整性并提供了崩溃恢复和回滚机制。 索引类型 MyISAM只支持表级锁定对于大量的读操作和少量的写操作性能较好。InnoDB使用B树索引支持行级锁定对于大量的读写操作性能较好。 崩溃恢复 MyISAM在崩溃后需要执行修复操作来恢复数据一致性修复过程相对较慢。而InnoDB通过事务的日志和redolog来实现快速崩溃恢复。
总的来说MyISAM对于读操作较多的应用场景和小型网站更适合而InnoDB适用于需要事务支持、并发性要求高以及数据完整性的应用特别是对于大型的OLTP系统。在选择存储引擎时需要根据应用的特点和需求进行综合考虑。
InnoDB存储引擎: 主要面向OLTP(Online Transaction Processing在线事务处理)方面的应用是第一个完整支持ACID事务的存储引擎(BDB第一个支持事务的存储引擎已经停止开发)。 特点
1 支持行锁 2 支持外键 3 支持自动增加列AUTO_INCREMENT属性 4 支持事务 5 支持MVCC模式的读写 6 读的效率低于MYISAM 7.写的效率高优于MYISAM 8.适合频繁修改以及设计到安全性较高的应用 9.清空整个表的时候Innodb是一行一行的删除
MyISAM存储引擎: 是MySQL官方提供的存储引擎主要面向OLAP(Online Analytical Processing,在线分析处理)方面的应用。
特点
1 独立于操作系统当建立一个MyISAM存储引擎的表时就会在本地磁盘建立三个文件例如我建立tb_demo表那么会生成以下三个文件tb_demo.frm,tb_demo.MYD,tb_demo.MYI 2 不支持事务 3 支持表锁和全文索引 4 MyISAM存储引擎表由MYD和MYI组成MYD用来存放数据文件MYI用来存放索引文件。MySQL数据库只缓存其索引文件数据文件的缓存交给操作系统本身来完成 5 MySQL5.0版本开始MyISAM默认支持256T的单表数据 6.选择密集型的表MYISAM存储引擎在筛选大量数据时非常迅速这是他最突出的优点 7.读的效率优于InnoDB 8.写的效率低于InnoDB 9.适合查询以及插入为主的应用 10.清空整个表的时候MYISAM则会新建表
简述mysql中索引类型有哪些以及对数据库的性能的影响
普通索引允许被索引的数据列包含重复的值
唯一索引可以保证数据记录的唯一性
主键索引是一种特殊的唯一索引在一张表中只能定义一个主键索引主键用于唯一标识一条记录使用关键字primary key来创建
联合索引索引可以覆盖多个数据列
全文索引通过建立倒排索引可以极大的提升检索效率解决判断字段是否包含的问题是目前搜索引擎使用的一种关键技术
索引可以极大地提高数据的查询速度
通过使用索引可以在查询的过程中使用优化隐藏器提高系统的性能
但是会降低插入、删除、更新表的速度因为在执行这些写操作的时候还要操作索引文件
索引需要占物理空间除了数据表占数据空间之外每一个索引还要占一定的物理空间如果要简历聚簇索引那么需要的空间就会更大如果非聚簇索引很多一旦聚簇索引改变那么所有非聚簇索引都会跟着变 mysql聚簇和非聚簇索引的区别
都是B树的数据结构 聚簇索引将数据存储与索引放到了一块、并且是按照一定的顺序组织的找到索引也就找到了数 据数据的物理存放顺序与索引顺序是一致的即只要索引是相邻的那么对应的数据一定也是 相邻地存放在磁盘上的 非聚簇索引叶子节点不存储数据、存储的是数据行地址也就是说根据索引查找到数据行的位置 再取磁盘查找数据这个就有点类似一本树的目录比如我们要找第三章第一节那我们先在这个 目录里面找找到对应的页码后再去对应的页码看文章。