一、Spring事务在哪种情况下会失效
- 如果在事务方法内部捕获了异常并不将其抛出,Spring 无法感知到异常的存在,事务不会回滚
- Spring 默认情况下是单事务管理器的,如果在一个事务方法内操作了多个数据库或事务管理器,则可能会导致事务失效
- 如果在一个事务方法内部使用
new
关键字直接创建对象,这个对象将不受 Spring 容器的管理,因此也不受事务管理的控制 - 如果一个事务方法内部调用了该类的其他方法,并且被调用的方法也有事务注解,那么事务可能会失效
二、为什么要选择innoDB数据库
- InnoDB 是一个支持事务的存储引擎,它遵循 ACID(原子性、一致性、隔离性、持久性)特性,可以确保数据的完整性和一致性。
- InnoDB 支持自动增长的列,可以方便地为表中的主键列生成唯一的标识符
- InnoDB 支持外键约束,可以在数据库层面上保证数据的完整性。
- InnoDB 支持行级锁定,允许多个事务同时操作同一张表的不同行,从而减少了由锁定导致的资源争用和阻塞。
- 在大规模的生产环境中被广泛使用,已经证明了其可靠性和稳定性
三、说一下乐观锁和悲观锁,在什么时候使用
乐观锁的基本思想是假设在数据被修改时不会发生冲突。适用于
- 数据读取操作较多,更新操作较少的场景。
- 并发冲突较少的场景。
- 不希望因为锁定而影响系统的并发性能的场景
悲观锁的基本思想是假设在数据被修改时会发生冲突。适用于
- 数据更新操作较多的场景。
- 并发冲突较为频繁的场景。
- 希望确保数据一致性和完整性的场景。
四、说一下敏捷开发
- 敏捷开发强调团队成员之间的互动和合作,重视面对面的沟通,认为良好的沟通能够促进理解和合作。
- 敏捷开发倡导通过编写可工作的软件来表达需求和设计,而不是依赖繁琐的文档。
- 敏捷开发强调与客户的密切合作,通过持续的交互和反馈来理解客户需求,并根据客户的反馈及时调整和改进软件。
- 敏捷开发认识到需求和环境的不断变化,鼓励团队灵活应对变化,及时调整计划和优先级,以满足客户的需求。
五、你会如何构造一个通用的后端模板
- 选择流行的后端框架,如Spring Boot
- 选择合适的数据库技术,如MySQL
- 设计清晰的项目结构,包括分层架构(如控制器、服务层、数据访问层)和模块化组织方式
- 集成安全性措施,包括数据加密、身份验证和授权,以确保系统安全性
- 设计健壮的错误处理机制,包括异常处理、错误码定义和友好的错误信息提示,以便于调试和问题定位。
- 设计清晰、简洁、统一的 API 接口,提供标准的 HTTP 方法(GET、POST、PUT、DELETE)和状态码
- 编写单元测试和集成测试,覆盖关键业务逻辑和接口,以确保系统的稳定性和正确性
- 提供简单的部署和配置方式,支持自动化部署和持续集成,以提高开发效率和部署灵活性。
六、hash冲突怎么解决
- 再哈希法,当一次哈希运算产生哈希冲突时,再进行一次哈希运算重新计算哈希值,直到没有冲突为止
- 再散列法,当产生冲突时,就寻找另一个地址,直到不冲突为止,将元素放入其中,若整个空间都没有空余的地址,则产生溢出
- 公共溢出区,就是在哈希表之外创建一个公共溢出区,专门用来存放产生哈希冲突的元素
- 链表加扩容后重新计算hash
七、mysql数据库有哪些锁机制
- 表级锁,表级锁是最粗粒度的锁,它可以锁定整个表,防止其他事务对整个表进行修改。MySQL 中的表级锁包括读锁(共享锁)和写锁(排它锁)
- 行级锁,行级锁允许同时对同一张表的不同行进行并发操作。MySQL 提供了多种行级锁,如共享锁(读锁)和排它锁(写锁),以及更细粒度的锁,如意向锁(Intention Locks)、间隙锁(Gap Locks)和next-key锁等
- 页级锁,MySQL 中的 MyISAM 存储引擎支持页级锁,即在对表进行读写操作时,会锁定表中的整个页面(Page),而不是单独的行
- 元数据锁,元数据锁用于锁定数据库对象(如表、数据库、存储过程等)的元数据信息,防止其他事务对元数据进行修改。元数据锁是在事务中自动获取的,不需要显式加锁
八、说明MySQL事务隔离的级别
- 读未提交,最低的隔离级别,允许事务读取其他事务未提交的数据,可能会导致脏读、不可重复读和幻读的问题。
- 读已提交,保证事务只能读取其他事务已经提交的数据,防止脏读的问题。但是可能会导致不可重复读和幻读的问题。
- 可重复读,在同一事务内多次读取同一数据时,保证所读取的数据是一致的,防止不可重复读的问题。但是仍然可能会导致幻读的问题。
- 串行化,最严格的隔离级别,确保事务之间完全隔离,不会发生并发问题。串行化隔离级别会对所有读取的数据进行锁定,直到事务结束。
九、说一下死锁
死锁是指两个或多个事务在互相等待对方持有的资源而无法继续执行的情况
死锁必要条件
- 互斥条件:一个资源每次只能被一个事务使用,即在一段时间内某个资源只能被一个事务占用。
- 持有并等待条件:一个事务可以持有一些资源并且在等待其他事务释放它所需要的资源。
- 不可剥夺条件:系统不能强行抢占一个事务已经占有的资源,只能等待其主动释放。
- 循环等待条件:一组事务之间形成一种循环等待资源的关系。
为了避免死锁的发生,可以采取以下策略:
- 加锁顺序:尽量按照固定的顺序获取锁,以避免循环等待条件的发生。
- 事务超时:为事务设置超时时间,在超时后自动释放资源并回滚事务,防止长时间等待。
- 死锁检测和回避:定期检测系统中是否存在死锁,并通过回滚某些事务来解除死锁。
- 减少事务持有资源的时间:尽量减少事务持有资源的时间,尽快释放资源,降低发生死锁的概率。
- 使用锁粒度小的锁:尽量使用行级锁而不是表级锁,减少锁冲突的可能性。
十、Spring框架中都用到了哪些设计模式
- 单例模式:Spring 中的 Bean 默认都是单例的,通过容器管理,保证在整个应用中只有一个实例。
- 工厂模式:Spring 中的 BeanFactory 和 ApplicationContext 采用了工厂模式,用于创建和管理对象实例。
- 代理模式:Spring AOP(面向切面编程)采用了代理模式,在目标对象的方法执行前后插入增强逻辑。
- 装饰器模式:Spring 中的装饰器(Decorator)可以动态地给一个对象添加一些额外的职责,从而实现功能的增强。
- 观察者模式:Spring 的事件(Event)机制采用了观察者模式,用于发布-订阅模式,实现模块间的耦。
- 策略模式:Spring 的 Bean 定义中可以通过设置不同的实现类来实现不同的策略,用于在运行时选择算法。
- 模板模式:Spring 中的 JdbcTemplate 和 HibernateTemplate 等模板类采用了模板模式,提供了模板化的数据库访问和数据操作方式。
- 适配器模式:Spring MVC 中的 HandlerAdapter 用于将请求适配到不同类型的处理器(Handler)上。
- 享元模式:Spring 中的 Bean 的作用域可以设置为 prototype,即原型模式,用于创建多个相同类型的对象。
- 链式调用模式:Spring 中的 Bean 的配置采用了链式调用的方式,如 bean.property1().property2().init()。
- 模板回调模式:Spring 中的 JdbcTemplate 等类采用了模板回调模式,将变化的部分封装成模板,将不变的部分通过回调方法留给用户自定义。