吐槽一下,我写技术文章从来没有像这个离职文章涨粉快。
个人愚见,公司最重要的是data
然后是一致性、安全性
涉及分布式
一。PgSQL和MySQL的区别
PostgreSQL在SQL的标准实现上要比MySQL完善,功能实现更加严谨。
PostgreSQL对表的连接支持更加完整,支持更多的SQL语法和功能。
PostgreSQL的优化器功能完整,支持多种索引类型,如B-tree、Hash、GiST、SP-GiST和BRIN等,可以根据不同的查询需求选择合适的索引类型。
MySQL的优化器相对简单,主要支持B-tree索引,但在新版本中也开始支持其他类型的索引。
PostgreSQL提供了强大的存储过程和函数语言PL/pgSQL,以及其他多种语言支持,如Python、Java等。
MySQL也支持存储过程和函数,但在功能和灵活性上相对较弱。
PostgreSQL支持丰富的数据类型,包括数组、JSON、XML等复杂数据类型,在处理半结构化和非结构化数据时更加灵活。
MySQL也支持多种数据类型,但相对来说没有PostgreSQL那么丰富。
PostgreSQL使用多版本并发控制(MVCC)来处理并发读写操作,性能稳定且高效。
MySQL也支持MVCC,但在一些复杂的并发场景下,可能需要更多的配置和优化。
MySQL和PostgreSQL在执行不同类型的查询时具有不同的性能表现。MySQL在处理简单查询时通常更快,而PostgreSQL在处理具有多个连接和较复杂查询逻辑的大型数据集时更有优势。例如,当处理大量的关联表和复杂的统计查询时,PostgreSQL通常表现得更好。
SELECT * FROM table1
JOIN table2 ON table1.id = table2.id
WHERE table1.column1 = 'value1' AND table2.column2 = 'value2';
二。MySQL对千万级的大表要怎么优化
1.搭建HA平台
2.增加索引
3.分库分表
4.查询优化
5.设置缓存
6.大数据平台
7.设置读写分离
8.加分区子分区
9,硬件内存增加nvme进行处理
增加索引
- 分析和理解表结构和查询模式
表中有哪些列?
哪些列经常用于查询条件(WHERE子句)?
哪些列经常用于排序(ORDER BY)?
哪些列用于连接(JOIN)?
哪些列用于分组(GROUP BY)?
单列索引是最简单的索引形式,适用于单列查询条件。
CREATE INDEX idx_column_name ON table_name (column_name);
组合索引
对于多列组合的查询条件,可以使用组合索引。注意组合索引的列顺序应与查询条件中的列顺序一致。
CREATE INDEX idx_column1_column2 ON table_name (column1, column2);
唯一索引
如果某列的值是唯一的,可以创建唯一索引,这不仅能提高查询性能,还能保证数据的唯一性
CREATE UNIQUE INDEX idx_unique_column ON table_name (column_name);
全文索引
如果需要对文本列进行全文搜索,可以创建全文索引。
CREATE FULLTEXT INDEX idx_fulltext_column ON table_name (column_name);
使用覆盖索引
覆盖索引是指查询所需的所有列都包含在索引中,这样可以直接从索引中获取数据,而无需访问表中的数据行。
CREATE INDEX idx_covering ON table_name (column1, column2, column3);
不要创建冗余的索引,因为每个索引都会占用额外的存储空间,并且在插入、更新和删除操作时都会增加额外的维护开销。
使用 EXPLAIN 语句来查看查询的执行计划,确定是否有效地使用了索引。
EXPLAIN SELECT * FROM table_name WHERE column_name = 'value';
更新统计信息:定期运行 ANALYZE TABLE 来更新表的统计信息,帮助优化器更好地选择执行计划。
ANALYZE TABLE table_name;
重建和优化索引:定期重建和优化索引,以恢复因频繁插入、更新和删除操作导致的索引碎片化。
OPTIMIZE TABLE table_name;
分库分表
在这里插入代码片
数据一致性问题
超卖问题是典型的多线程安全问题,针对这一问题的常见解决方案就是加锁:而对于加锁,我们通常有两种解决方案
悲观锁与乐观锁
悲观锁:
如果我们多个线程是串行执行的,就不会出现安全问题了。所以这就是悲观锁的实现思想,既然多线程并发有安全问题,那你就不要并发执行了。正因为如此,悲观锁的性能就不是很好,因为你不管有多少线程,都只能一个一个的去执行,因此高并发的场景下悲观锁并不是很适合。
JDK中提供的syn,和lock、数据库中的互斥的锁,都是悲观锁的代表,同时,悲观锁中又可以再细分为公平锁,非公平锁,可重入锁,等等。
乐观锁
因为乐观锁折后转给你方案它不用加锁,而是在执行时才做一个判断,因此它的性能要比悲观锁好很多。
但是它的关键点在于:我怎么知道在我更新的时候别人有没有来做修改?因此这个判断成为了关键,这也是我们接下来要研究的。
悲观锁比较简单,相信大家都会,这里就不演示了,这里就演示乐观锁
同一时间多次操作,操作时对比版本号
实现方式一:版本号法
实现方式二:CAS
-- 假设表有一个名为version的字段
START TRANSACTION;
-- 获取当前数据及其版本号
SELECT version FROM your_table WHERE your_unique_column = 'some_value' FOR UPDATE;
-- 假设获取到的版本号为current_version
-- 更新时检查版本号
UPDATE your_table
SET other_column = 'new_value', version = current_version + 1
WHERE your_unique_column = 'some_value' AND version = current_version;
-- 检查更新是否成功(影响的行数)
IF (ROW_COUNT() = 0) THEN
-- 冲突发生,回滚事务
ROLLBACK;
ELSE
-- 更新成功,提交事务
COMMIT;
END IF;
MVCC
数据库(包括 MySQL、Oracle、PostgreSQL 等)引擎实现中常用的处理读写冲突的手段,目的在于提高数据库高并发场景下的吞吐性能。
不同的事务在并发过程中,SELECT 操作可以不加锁而是通过 MVCC 机制读取指定的版本历史记录,并通过一些手段保证保证读取的记录值符合事务所处的隔离级别,从而解决并发场景下的读写冲突。
为什么需要 MVCC
InnoDB 相比 MyISAM 有两大特点,一是支持事务而是支持行级锁,事务的引入带来了一些新的挑战。相对于串行处理来说,并发事务处理能大大增加数据库资源的利用率,提高数据库系统的事务吞吐量,从而可以支持可以支持更多的用户。但并发事务处理也会带来一些问题,主要包括以下几种情况:
更新丢失(Lost Update):当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题 —— 最后的更新覆盖了其他事务所做的更新。如何避免这个问题呢,最好在一个事务对数据进行更改但还未提交时,其他事务不能访问修改同一个数据。
脏读(Dirty Reads):一个事务正在对一条记录做修改,在这个事务并提交前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些尚未提交的脏数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象地叫做 “脏读”。
不可重复读(Non-Repeatable Reads):一个事务在读取某些数据已经发生了改变、或某些记录已经被删除了!这种现象叫做“不可重复读”。
幻读(Phantom Reads):一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为 “幻读”。
以上是并发事务过程中会存在的问题,解决更新丢失可以交给应用,但是后三者需要数据库提供事务间的隔离机制来解决。