MySQL 面试题
NoSQL和SQL的区别?
SQL(Structured Query Language,结构化查询语言),代表数据库:SQL Server,Oracle,MySQL(开源),PostgreSQL(开源)。 NoSQL(Not Only SQL,不仅仅是SQL),代表数据库:MongoDB,Redis 关系型数据库存储结构化数据。这些数据逻辑上以行列二维表的形式存在,每一列代表数据的一种属性,每一行代表一个数据实体。
数据库三大范式是什么?
NF:Normal Form
- 第一范式(1NF):原子性(每一列都是不可分割的原子数据项, 储的数据应该具有“不可再分性”)
- 第二范式(2NF):唯一性,消除部分依赖 (消除非主键部分依赖联合主键中的部分字段)(一定要在第一范式已经满足的情况下)
- 第三范式(3NF):独立性,消除传递依赖(非主键值不依赖于另一个非主键值)
datetime 和timestamp有什么区别?
CHAR 和 VARCHAR 有什么区别?
CHAR是长度固定字符串, VARCHAR是可变长度字符串
什么是数据库约束?常见数据库约束有哪些?
约束是限制数据的插入.
- 外键约束 foreign key
- 主键约束 primary key
- 默认值约束 default value
- 非空约束 not null
- 唯一约束 unique
什么是数据库事务?
事务是逻辑上的一组操作,要么都执行,要么都不执行。 数据库事务是指多个对DB的操作(SQL 语句)构成一个逻辑上的整体,构成这个逻辑上的整体的DB操作:要么全部执行成功, 要么全部不执行.
数据库事务有哪些特点(AIDC)?
- 原子性(Atomicity)事务中的操作,要么全部执行成功, 要么全部不执行
- 隔离性(Isolation)并发事务之间相互独立互不干扰
- 持久性(Durability)事务提交后数据会持久化存储, 数据不丢失
- 一致性(Consistency)事务执行前后,数据逻辑总量保持一致
MySQL的默认隔离级别是什么?
MYSQL的默认隔离级别是: 可重复读 Repeatable Read Oracle、SQL Server的默认隔离级别是读已提交 Read Committed
并发事务带来了什么问题?
- 脏读(Dirty Read)事务A读到了事务B未提交的数据(Insert, Update, Delete)
- 虚读(Virtual Read)又称不可重复读(Unrepeatable Read) 事务A多次读取, 读到了事务B已提交的更新(Update). 行数据内容变更.
- 幻读(Phantom read)事务A多次读取, 读到了事务B已提交的增(Insert)删(Delete). 总行数变更
数据库事务的隔离级别有哪些?
- 读未提交(Read Uncommitted) 存在脏读、虚读、幻读
- 读已提交(Read Committed) 解决脏读,存在虚读、幻读
- 可重复读(Repeatable Read) 解决脏读、虚读, 存在幻读(InnoDB已解决)
- 串行化(Serializable) 解决脏读、虚读、幻读,性能较低
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | 存在 | 存在 | 存在 |
读已提交 | 解决 | 存在 | 存在 |
可重复读 | 解决 | 解决 | 存在(InnoDB已解决) |
串行化 | 解决 | 解决 | 解决 |
不可重复读和幻读的区别是什么?
侧重点不同, 不可重复读(虚读)侧重数据的内容, 幻读侧重数据的数量
count(*) count(1) count(列名) 有什么区别?
count(*) 统计表行数
count(1) 统计表函数
count(column) 统计column的非null行数
效率:
count(*) = count(1)
count(column) 会判断列是否为null
java
package com.luruoyang.controller;
import com.luruoyang.enums.BusinessType;
import com.luruoyang.repository.ChatHistoryRepository;
import com.luruoyang.repository.RedisChatHistoryRepositoryImpl;
import com.luruoyang.vo.MessageVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.springframework.ai.chat.client.advisor.AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY;
/**
* @author luruoyang
*/@RestController
@RequestMapping("/ai")
@Slf4j
public class ChatController {
@Autowired
private ChatClient chatClient;
@Autowired
private ChatHistoryRepository chatHistoryRepository;
@Autowired
private RedisChatHistoryRepositoryImpl redisChatHistoryRepository;
@Autowired
@Qualifier("redisChatMemory")
private ChatMemory chatMemory;
/**
* 同步调用
*/
@RequestMapping("/chat2")
public String chat(@RequestParam(value = "prompt", defaultValue = "你是谁?") String prompt) {
String assistant = chatClient.prompt(prompt).call().content();
return assistant;
}
/**
* 流式调用
*/
@RequestMapping(value = "/chat", produces = "text/html;charset=UTF-8", method = RequestMethod.POST)
public Flux<String> chatWithStream(
@RequestParam(value = "prompt", defaultValue = "给我讲一个计算机编程领域的笑话?") String prompt,
@RequestParam("chatId") String chatId
) {
log.info("chatId: {}", chatId);
log.info("prompt: {}", prompt);
// 保存会话ID
// chatHistoryRepository.saveHistory(BusinessType.fromValue("chat"), chatId); redisChatHistoryRepository.saveHistory(BusinessType.fromValue("chat"), chatId);
Flux<String> content = chatClient
.prompt()
.user(prompt)
/* 区分不同会话 */ .advisors(advisorSpec -> advisorSpec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId))
.stream()
.content();
return content;
}
/**
* 查询会话ID列表
*/
@GetMapping("/history/{businessType}")
public List<String> getChatIdsByBusinessType(@PathVariable("businessType") String businessType) {
// return chatHistoryRepository.getChatIdsByType(businessType);
return redisChatHistoryRepository.getChatIdsByType(businessType);
}
/**
* 根据会话ID查询会话历史记录
*/
@GetMapping("/history/{businessType}/{chatId}")
public List<MessageVO> getChatHistoryByTypeAndChatId(
@PathVariable("businessType") String businessType,
@PathVariable("chatId") String chatId) {
List<Message> messages = chatMemory.get(chatId, Integer.MAX_VALUE);
if (messages.isEmpty()) {
return List.of();
}
return messages.stream().map(MessageVO::new).collect(Collectors.toList());
}
}