PythonLearn

使用数据库保存数据

假设你有个星际游戏,包含飞船组装内容,地图中的星球数据,你会怎么保存,json可以,但对于很大的数据就不合适了, 这时候就推荐数据库了。

如果是游戏,本地的用sqlite,如果是网站,那就用postgresql或其他,至于mysql,用之前记得上网搜搜它的坑。

事先声明

本章不包含安装教程和基础增删改查语法,这种网上全是教程
本章包含数据库进阶知识,比如索引,事务,锁,时区等等
以下全部按照自己的理解思路编写

事务

事务可以确保你的两个数据库操作,即要么同时成功,要么同时失败
而同一时间的事务肯定不止一个,所以,事务的隔离级别也就是定义别人的事务对你事务的影响

隔离级别通常在创建会话时设置,不设置就是用默认的

-- 设置 会话 事务         隔离         级别   (隔离级别)
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

mysql的默认隔离级别是“可重复读”,其他常见的是“读已提交”

隔离级别

| 隔离级别 | 底层说明 | |————————|:——————| | 串行化(SERIALIZABLE) | 会锁住自己查询范围,直到提交 | | 可重复读(REPEATABLE READ) | 会锁住自己查询到的所有行,直到提交 | | 读已提交(READ COMMITTED) | 读数据库,会在读取时锁住行 | | 读未提交(READ UNCOMMITTED) | 先读其他事务,再读数据库 |

简化成一句话

注意:目前有很多数据库都支持使用多版本并发控制(MVCC)来实现快照隔离,这通常比完全锁定的性能更好。

关键名词

接下来就可以看看不同事务对这些名词的关系了

隔离级别 脏读 不可重复读 幻读
SERIALIZABLE 不会发生 不会发生 不会发生
REPEATABLE READ 不会发生 不会发生 会发生
READ COMMITTED 不会发生 会发生 会发生
READ UNCOMMITTED 会发生 会发生 会发生

你看,“可重复读”不会发生“不可重复读”的问题

mysql专区

注意,在旧版mysql里,DDL>TRANSACTION,所以当你在事务里删除一个表,回退时这个表不会被还原的哦,哦吼,完蛋

时区

为什么要设置时区

你在今天早上6点起了床,当你的美国朋友查看你的起床时间时,结果是6点,嗯,和他起的一样早……(任何国家的早晨都是当地时间6点)
事实上你在美国的晚上起来的,这就是时区问题,美国比我们晚了6个小时,如果你希望按照美国的时区获取时间,那么你需要处理时区

会话的时区

为了解决上面的问题,我们需要设置当前会话的时区,来确保读取日期时,返回的是当前时区中那个时间 不同数据库设置时区方式不同,比如SQL Server……这个不能设置时区
比如postgresql

SET TIMEZONE = 'Asia/Shanghai';

为什么要保存时区信息

直接统一存储为UTC时间,根据不同会话的时区,返回不同时区的时间不行吗?
因为有个夏令时问题,在部分地区,如果你不保存时区信息,系统就无法正确知道该事件是在夏令时还是标准时。

数据库区别

不同数据库的类型和作用不一样,但DATE, TIME, DATETIME基本都一样,只保存时间,不包含日期

但比如TIMESTAMP,在postgresql中不带时区,需要TIMESTAMP WITH TIME ZONE才能包含时区信息
而在mysql中,TIMESTAMP返回时根据当前时区返回不同结果,但是存储时仍不带时区,这就会遇到夏令时问题,不愧是你
在sqlserver,TIMESTAMP甚至不是存储时间的,存储日期的是DATETIMEOFFSET

默认时区

按安装数据库时一般是本地时区,可以手动设置,用于在会话没有设置时区时使用默认时区

优化

在视频网站中,每个点赞都需要插入一条数据,那么可想而知,哔哩哔哩有多少亿个点赞数据了

分表

分表是将大表拆分成多个小表的操作,能够有效减轻单一表的压力,提升查询和插入的效率。 比如按照时间分表,或者按照ID分表,没什么好说的
此外还有个分库操作

缓存

针对热点数据,将数据缓存到Redis中,减少数据库查询,可提升查询效率,但要考虑数据一致性

索引

索引是加速数据库查询的关键,可以大大提升数据检索的速度。

读写分离

读写分离是数据库的优化策略,将读和写分离到不同的数据库服务器上,从而提升数据库的吞吐量。