MySQL锁机制

msql锁机制

概述

锁的定义

锁是计算机协调多个进程或线程并发访问某一资源的机制。

在数据库中,除传统计算机资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供许多用户共享的资源,如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突是影响数据库并发性能的一个重要因素,从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。

RAM:Random Access Memory,随机存取存储器。

锁的分类

XXXXXXXX

MyISAM的锁机制

MYSQL事务

1
2
3
4
5
6
7
8
9
10
1、用 BEGIN, ROLLBACK, COMMIT 来实现

BEGIN 或 START TRANSACTION:开用于开始一个事务。
ROLLBACK 事务回滚,取消之前的更改。
COMMIT:事务确认,提交事务,使更改永久生效。

2、直接用 SET 来改变 MySQL 的自动提交模式:

SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT=1 开启自动提交

表锁(偏读)

1
2
3
4
5
表锁
读锁(共享锁):加读锁(对当前表),当前session可读不可写,且不可读取其他未加锁的表,其他session对该表可读不可写。
MySQL早期版本(如5.5及之前)中,MyISAM表在读取数据时会自动加读锁,但写操作不会自动加锁。现在,MyISAM 表在读取数据时默认不会自动加锁,除非使用了 LOCK TABLES 语句手动加锁。

加写锁(互斥锁):当前能读和写,阻塞其他线程的读和写(等待)。

建表sql

释放表锁

unlock tables;(上表in_use项全部变为0)

加读锁

加写锁

总结

表锁分析

lnnoDB的锁机制

行锁(偏写)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
共享锁(读锁):简称S锁,当一个事务对某几行上读锁时,允许其他事务对这几行进行读操作,但不允许其进行写操作,允许其他事务上读锁,但不允许给这几行上写锁。

排他锁(写锁):简称X锁,当前事务对加了写锁的行可以进行读取和写入,可以自由地读取表中其他未被加锁的行。其他事务对这些加了写锁的行既不能读取也不能写入,也不能给这几行上任何锁。

如果其他事务使用的是“一致性非锁定读”(通过MVCC机制),它们仍然可以读取这些行的快照版本,而无需等待锁释放。这种读取方式不会获取锁,因此不会被写锁阻塞。这是InnoDB 实现并发性能的一个关键特性。

注意:
1.行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了。
2.insert ,delete , update在事务中都会自动默认加上排它锁。

行锁和索引的关系:
InnoDB通过索引可以快速地定位到需要锁定的行。如果没有索引,由于无法高效地定位到特定的行进行锁定,就只能将整个表锁定,以保证数据的一致性。

一致性非锁定读:
是指在读取数据时,不会对数据行加锁。它会读取数据行的一个一致性视图,这个视图是根据事务的隔离级别和事务开始时的状态来确定的。
当一个事务执行一致性非锁定读时,InnoDB 会根据事务的隔离级别和事务的快照版本来查找数据。例如,在可重复读隔离级别下,事务会看到事务开始时的数据快照,这个快照是通过多版本并发控制(MVCC)实现的。MVCC 为每行数据保存多个版本,每个版本都有一个事务的标识,用于确定该版本是哪个事务修改的。

一致性非锁定读是否能读取最新的提交数据,取决于事务的隔离级别。在读已提交(Read Committed)隔离级别下,一致性非锁定读可以读取最新的已提交数据。在可重复读(Repeatable Read)隔离级别下,一致性非锁定读不能读取最新的提交数据。在可重复读隔离级别下,事务在开始时会创建一个数据的快照,后续的读操作都基于这个快照。即使其他事务对数据进行了修改并提交,只要这个事务还没结束,它仍然会看到事务开始时的数据版本。
例如:事务 A 在可重复读隔离级别下查询一张表得到某些数据行。事务 B 修改了这些数据行并提交。事务 A 再次查询这些数据行时,还是看到第一次查询时的数据,不会读取到事务 B 提交后的最新数据,这是为了保证事务内的可重复读。

行锁基本演示

建表

取消自动提交就是设置了行锁,不提交前具有己读性(只有自己能看到修改后的数据,其他人看旧数据)

若两边操作不同的行,则不阻塞,提交后能看到修改的数据

无索引,行锁升级为表锁:

设置了行锁,但session1更新时b为varchar却没有加单引号,导致索引失效,未提交,导致升级为表锁,session2出现等待,session1提交后,session2恢复

如何主动锁定一行

select … … for update(排它锁); select … lock in share mode(共享锁)

结论

1555903650349

如何分析行锁

页锁

知道有这么个锁就可以,用的比较少

扩展:

1.什么情况会加锁:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
1.对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及的数据集加排他锁;
2.对于普通SELECT语句,InnoDB不会加任何锁;如果在SELECT语句中使用了锁定提示(如SELECT ... FOR UPDATE或SELECT ... LOCK IN SHARE MODE),InnoDB会根据提示对读取的行加锁。
在事务中读取数据不会加读锁而是使用一致性非锁定读,只有加了锁定提示,才会加读锁。

其他情况:
1.当执行涉及外键约束的操作时,InnoDB可能会对相关表中的行加锁以确保约束的一致性。例如,当插入或更新带有外键的行时,InnoDB会检查父表中的相关行是否存在,并可能对这些行加锁以防止它们被删除或修改。
2.如果在表上定义了触发器,当触发器被激活时,InnoDB可能会对相关行加锁。这取决于触发器的定义和执行的操作。
3.在存储过程或函数中执行的SQL语句可能会导致加锁。这取决于存储过程中包含的语句类型。
4.在可重复读隔离级别下,InnoDB会使用间隙锁(Gap Locks)和next-key锁(记录锁 + 间隙锁)来防止幻读。这些锁会锁定索引间隙或索引记录,防止其他事务插入或更新数据。
间隙锁是否任何时候都存在呢?
5.在某些情况下,如对表进行DDL操作(如ALTER TABLE)、对没有索引的表进行大量更新或删除操作时,InnoDB可能会使用表锁而不是行锁。

外键约束:
外键(Foreign Key)是一种用于确保数据一致性的数据库约束,通常用于关联两个表中的数据,数据库管理系统(如MySQL)会在内部维护这些约束信息。
-数据一致性,外键约束确保引用的值在被引用的表中存在。当试图插入或更新一个外键值时,数据库会检查被引用的表中是否存在该值。如果不存在,操作会被拒绝。
-级联操作,可以定义外键的级联操作,如ON DELETE CASCADE或ON UPDATE CASCADE,以便在被引用的行被删除或更新时,自动更新或删除引用的行。
-事务支持,外键约束通常与事务一起使用,以确保数据的一致性。在事务中,对外键的检查通常会在事务提交时进行。
CREATE TABLE students (
id INT PRIMARY KEY,
name VARCHAR(100),
class_id INT,
FOREIGN KEY (class_id) REFERENCES classes(id)
);
外键约束在实际开发中非常常见,尤其是在需要保证数据完整性和一致性的场景下。
不定义外键约束虽然在某些情况下可以简化开发或提高性能,但它可能导致数据不一致和应用逻辑复杂化。因此,建议在设计数据库时尽量使用外键约束,特别是在需要保证数据完整性和一致性的场景下。如果确实因为性能或其他原因不能使用外键约束,应在应用层实现相应的逻辑来确保数据的一致性。

触发器(Trigger):
是一种特殊类型的数据库存储过程,它会根据预定义的事件(如插入、更新或删除操作)自动执行。触发器可以用来在数据变动时自动执行一系列操作,以确保数据的完整性、一致性或执行其他业务逻辑。
BEFORE 触发器:在执行INSERT、UPDATE或DELETE操作之前触发。通常用于验证或修改将要插入或更新的数据。
AFTER 触发器:在执行INSERT、UPDATE或DELETE操作之后触发。通常用于在数据更改后执行某些操作,如记录日志或更新其他表。
触发器通过CREATE TRIGGER语句定义。
BEFORE INSERT 触发器例子:
DELIMITER //
CREATE TRIGGER before_employee_insert
BEFORE INSERT ON employees
FOR EACH ROW
BEGIN
-- 在插入新员工记录时,设置创建时间和修改时间
SET NEW.created_at = NOW();
SET NEW.updated_at = NOW();
END //
DELIMITER ;

AFTER UPDATE 触发器例子:
DELIMITER //
CREATE TRIGGER after_employee_update
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
-- 在更新员工记录后,记录日志
INSERT INTO employee_logs (employee_id, action, timestamp)
VALUES (OLD.id, 'UPDATE', NOW());
END //
DELIMITER ;

作用:
1.数据完整性:触发器可以用于在插入或更新数据时验证数据的正确性。例如,确保某个字段必须为正数或者在插入新记录时自动生成某些字段的默认值。
2.自动记录日志:触发器可以用于记录数据变动的历史。例如,每次更新或删除一条记录时,可以将原数据保存到一个日志表中。
3.级联更新或删除:触发器可以用于在某个表的数据变动时自动更新或删除其他表中的相关数据。
4.业务逻辑实现:触发器可以用于实现一些业务逻辑,如在插入或更新数据时自动计算某些字段的值。

注意事项:
1.性能影响:触发器的逻辑可能会增加数据库操作的复杂性和执行时间。因此,在设计触发器时,应尽量保持其逻辑简单高效。
2.调试困难:触发器的逻辑在数据库内部执行,调试起来可能比较困难。需要通过日志或调试工具来跟踪触发器的执行情况。
3.事务处理:触发器中的操作通常会受到事务的影响。如果触发器中的操作导致错误,整个事务可能会回滚。
4.权限要求:创建和管理触发器通常需要特定的数据库权限。

总之,触发器是一种强大的数据库工具,可以用来自动执行各种操作以确保数据的一致性和完整性。但使用时应谨慎,以避免对性能和可维护性造成负面影响。

参考:https://www.cnblogs.com/hi3254014978/p/17107610.html

事物的ACID

事务的ACID特性是数据库系统中事务的四个关键特性,它们确保了事务能够可靠地执行,并且在发生故障或错误时能够保持数据的一致性和完整性。

1.原子性(Atomicity)

事务是个原子操作单元,事务要么完全执行,要么完全不执行。如果事务的一部分失败,整个事务将回滚,所有操作都不会对数据库产生影响。

2.一致性(Consistency)

事务执行前后,数据库都必须保持一致状态。这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性;事务结束时,所有的内部数据结构(如B树索引或双向链表)也都必须是正确的。

3.隔离性(Isolation)

事务的执行是独立的,不受其他并发事务的影响。每个事务都像是在独立的环境中运行,其操作和中间状态对其他事务不可见。

4.持久性(Durability)

一旦事务提交,其对数据库的修改就是永久的,即使之后发生系统故障,修改后的数据也不会丢失。

事物隔离级别与脏读、不可重复读、幻读的关系

一般来说数据库的默认级别是提交读(比如SQL Server、Oracle),而mysql的InnoDB事务的隔离级别 默认是“可重复读”(REPEATABLE READ)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1)未提交读(READ UNCOMMITTED)。另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据(脏读)( 隔离级别最低,并发性能高 )。
2)提交读(READ COMMITTED)。本事务读取到的是最新的数据(其他事务提交后的)。问题是,在同一个事务里,前后两次相同的SELECT会读到不同的结果(不重复读)。会出现不可重复读、幻读问题(锁定正在读取的行)
3)可重复读(REPEATABLE READ)。在同一个事务里,SELECT的结果是事务开始时的时间点状态,因此,同样的SELECT操作读到的结果会是一致的。但是,会有幻读现象(锁定所读取的所有行)。
4)串行化(SERIALIZABLE)。读操作会隐式获取共享锁,可以保证不同事务间的互斥(锁表)。serializable时会锁表,因此不会出现幻读的情况,包括更新丢失也能解决,但这种隔离级别并发性极低,开发中很少会用到

四个级别逐渐增强,每个级别解决一个问题。
1)脏读。另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据。
2)不可重复读。解决了脏读后,会遇到:另外一个事务提交了新数据,导致本事务先后两次读到的数据结果会不一致。
3)幻读。解决了不可重复读,保证了同一个事务里,查询的结果都是事务开始时的状态(一致性)。但若另一个事务同时提交了新数据,本事务再更新时,就会“惊奇的”发现了这些新数据,貌似之前读到的数据是“鬼影”一样的幻觉。

脏读和幻读的区别:脏读是事务b修改了数据,幻读是事务b新增了数据

隔离级别越高的数据库越安全,能解决的并发*一致性*问题也就越多。
隔离级别越高,就代表着越安全,但是同时性能效率也就越低。

参考链接:https://blog.csdn.net/ccfeng2008/article/details/51760350

并发事务会导致数据脏读、不可重复读、幻读、更新丢失

更新丢失(Lost Update)

两个事务在并发下同时进行更新,后一个事务的更新覆盖了前一个事务更新的情况,丢失更新是数据没有保证一致性导致的。比如,事务A 修改了一条记录,事务B 在 事务A 提交的同时也进行了一次修改并且提交。当事务A查询的时候,会发现刚才修改的内容没有被修改,好像丢失了更新。

解决办法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
1.使用适当的事务隔离级别:
可重复读
在可重复读隔离级别下,InnoDB使用多版本并发控制(MVCC)来避免更新丢失。当一个事务读取数据时,它读取的是事务开始时的数据快照,其他事务对数据的更新不会影响当前事务看到的数据。如果两个事务同时读取同一数据并进行更新,第二个事务在提交时会检测到数据已被修改,并根据具体情况决定是否抛出异常或回滚。
另外在这一级别下,InnoDB可以使用间隙锁和next-key锁来避免幻读,这些锁也可以间接避免更新丢失。间隙锁锁定索引间隙,防止其他事务在间隙中插入数据。next-key锁锁定索引记录和前面的间隙,确保数据的一致性。
串行化(SERIALIZABLE)
这是最高级别的隔离,它通过强制事务串行执行来避免更新丢失。在串行化隔离级别下,事务会获取读写锁,确保同一时间只有一个事务可以访问和修改数据。使用串行化隔离级别可以完全避免更新丢失,但会降低并发性能,因为事务必须按顺序执行,不能并行。
2.使用SELECT ... FOR UPDATE获取排他锁
行锁可以确保在更新数据时,其他事务不能同时对同一数据进行更新。InnoDB默认使用行锁,但在某些情况下可能需要显式地获取行锁。
这样可以确保在读取和更新数据时其他事务不能对该数据进行修改,从而避免更新丢失。
3.乐观锁
乐观锁是一种应用层面的锁机制,它假设在事务执行期间不会发生冲突,但在提交时会检查是否发生了冲突。如果发生冲突,则回滚事务并重试。
实现方式:通常在数据表中添加一个版本号(version)或时间戳(timestamp)字段。在更新数据时,检查当前版本号是否与读取时的版本号一致。如果不一致,说明数据已被其他事务修改,回滚当前事务并重试。
4.悲观锁
悲观锁(Pessimistic Locking)假设冲突是常见的,因此在读取数据时就加锁,以防止其他事务对数据进行修改。在事务执行期间,悲观锁会一直持有锁,直到事务完成。
在MySQL的InnoDB存储引擎中,可以通过SELECT ... FOR UPDATE语句来实现悲观锁。这个语句会对读取的行加排他锁,确保其他事务无法对这些行进行读写操作(除了同样持有排他锁的事务)。

InnoDB解决更新丢失与幻读:
更新丢失:在可重复读隔离级别下,InnoDB通过行锁和MVCC机制避免更新丢失。行锁确保同一行数据在同一时间只能被一个事务更新,而MVCC在事务提交时检测数据是否被修改。
幻读:在可重复读隔离级别下,InnoDB通过next-key锁避免幻读。next-key锁(间隙锁+记录锁)锁定索引记录之间的间隙和记录,防止其他事务插入新行。

在高并发的情况下,使用了mysql的事务,未加行锁的情况下是有可能更新丢失的,这时可以给事务加一个redis锁或者在事务中显示的加写锁,来防止并发。两者性能上的对比是
Redis锁:在高并发场景下性能较好,能快速响应,但需要额外的Redis组件,适用于分布式系统中的并发控制。
MySQL写锁:适合对数据一致性要求极高的场景,无需额外组件,但在高并发下可能会降低并发性能,适用于传统单体应用或对事务隔离性要求高的场景。

InnoDB引擎通过MVCC,解决了脏读、不可重复读,通过MVCC + Next-Key Lock(临键锁)来解决幻读,实现了事务的隔离级别Repeatable Read(可重复读)。

可重复读隔离级别下,并发问题需要靠开发者显式或隐式使用锁来自行解决。

参考链接:

https://blog.csdn.net/sun8112133/article/details/89853755

RR(Repeatable Read)防止幻读的讨论:

https://github.com/Yhzhtk/note/issues/42

结论:Innodb 的 RR 隔离界别对范围会加上 GAP,理论上不会存在幻读,但是是否有例外,还需要进一步求证。

扩展

间隙锁

范围检索数据时,对于键值在条件范围内但并不存在的记录,叫做"间隙( GAP )", InnoDB 也会对这个"间隙”加锁,叫间隙锁。这种锁机制就是所谓的Next - Key 锁(记录锁 + 间隙锁)。

Record Lock:即行锁或排他锁,锁定一个记录上的索引,而不是记录本身。只要表有主键,就存在聚簇索引,Record Lock可以作用于该索引。如果没有显式的主键或索引,InnoDB会创建隐藏的聚簇索引,Record Lock仍然可以使用。因此,表总是存在索引(至少是隐藏的聚簇索引),Record Lock总能作用于某个索引。

Gap Lock:间隙锁锁定的是索引记录之间的间隙,而不是具体的数据行本身。它用于保护一个范围内的记录,但不锁定记录本身。GAP锁的主要目的是防止幻读。幻读发生在在一个事务中多次执行相同查询时,由于其他事务插入了新数据,导致查询结果不一致。间隙锁通过锁定索引记录之间的间隙,阻止其他事务在这些间隙中插入新记录,从而避免幻读。间隙锁通常在可重复读隔离级别下自动使用。当执行范围查询(如 SELECT * FROM table WHERE id BETWEEN 1 AND 10 FOR UPDATE)时,InnoDB 会自动对符合条件的索引记录之间的间隙加锁。锁定的是两个相邻记录之间的间隙,不包含记录本身。若两个相邻记录的值分别是xy,则间隙锁的区间表示为(x, y)(左开右开区间)。

Next-Key Lock:是Record Lock和Gap Lock的组合,Next-Key Lock 锁定的是一个记录以及该记录之后的间隙,但不包括下一个记录,也就是说,它锁定的是一个左闭右开的区间[current_record, next_record)。Next-Key Lock 的主要目的是防止幻读。当执行范围查询非唯一索引上的等值查询(select…for update)操作时,InnoDB 会使用 Next-Key Lock。

GAP锁和Next Key Lock区别

区别在于锁定范围,Gap锁只锁定索引记录之间的间隙,而Next Key Lock则同时锁定索引记录和间隙。另外,Next Key Lock是MySQL中的一种锁机制,它是在Gap锁的基础上引入的,结合了 Gap 锁和记录锁的功能,提供了更强的保护。

当我们用范围条件,并请求共享或排他锁时, InnoDB 会给符合条件的已有数据进行加锁;即,一个事务在一个范围内的索引记录上执行SELECT ... FOR UPDATE语句时,MySQL会在该范围内的所有记录和间隙上设置Next Key Lock。

而若是使用相等条件检索数据(select),InnoDB只会对满足条件的记录加记录锁(Record Lock),而不会对间隙加锁。这种情况下,锁定范围仅限于被访问的记录本身,不存在区间加锁。

例子:

1
2
3
4
5
6
7
8
9
10
>set autocommit =0;
>update products set name= 'nums' where id < 10;
>commit;

会话1:用update语句更新符合条件的数据的某个字段值,更新条件为id<10,目前表中id只有1、2、3、4、6、9的数据,那么id=5,7,8的行数据也会被锁,即间隙行被锁(虽然实际数据不存在)
会话2:插入不存在但是处以id<10条件的行数据时,会进入阻塞状态,直到会话1提交事务。
如何避免:
1.尽量缩小where后面条件的范围,尽量让更新或删除操作的WHERE条件能够精确匹配索引,避免使用范围查询。如果必须使用范围查询,尽量让范围尽可能小,以减少锁定的间隙和记录。
2.使用唯一索引:如果可能,使用唯一索引可以避免间隙锁,因为唯一索引的等值查询不会锁定间隙。
3.调整事务隔离级别:如果幻读不是主要问题,可以考虑将事务隔离级别调整为读已提交(READ COMMITTED),在这个隔离级别下,InnoDB不会使用间隙锁。
CAP理论

分布式系统领域的理论

http://www.cnblogs.com/gudi/p/8183548.html

一致性C(Consistency)、可用性A(Availability)和分区容错性P(Partition Tolerance)

1
2
3
4
5
一致性(数据):当一个节点向系统写入数据后,其他节点立即能读取到这个最新的数据。这意味着任何节点的读操作都能获取到最新的写入结果。
可用性(系统):每个请求都必须在有限的时间内返回结果,无论成功还是失败。系统不能无限制地拖延响应。
分区容错性(网络):系统在遇到网络分区(部分节点之间的通信失败)时仍能继续运行。意味着即使在网络分区的情况下,系统仍然能够继续处理请求。

网络分区是指在分布式系统中,由于网络故障、配置错误或其他原因,导致系统中的一部分节点无法与另一部分节点进行通信。它不一定是因为某个地区的网络信号不可用,而更像是系统内部的通信故障,类似于国内的网络访问不了国外的网站。

CAP的权衡

在实际的分布式系统设计中,通常需要在以下三种组合中做出选择

1
2
3
1.CP系统(Consistency + Partition Tolerance):在这种系统中,当发生网络分区时,系统会优先保证一致性,可能会牺牲部分可用性。例如,某些节点可能无法响应请求,直到分区问题解决。如果系统选择保证一致性(CP),那么在分区期间,系统可能会拒绝部分请求以保持数据一致(如银行交易系统)。
2.AP系统(Availability + Partition Tolerance):在这种系统中,当发生网络分区时,系统会优先保证可用性,可能会牺牲一致性。例如,某些节点可能会返回过时的数据,但系统仍然会响应请求。如果系统选择保证可用性(AP),那么在分区期间可能会出现数据不一致的情况。(如在线视频服务,大网站一般保AP)
3.CA系统(Consistency + Availability):理论上,这种系统可以在没有网络分区的情况下同时满足一致性和可用性。但实际上,在分布式系统中,网络分区是不可避免的,因此CA系统在实际中很少存在

CAP理论实际应用

1
2
1.主从复制:在主从复制架构中,主节点负责写操作,从节点负责读操作。为了保证一致性,写操作需要在所有从节点上成功后才返回成功。但如果网络分区导致从节点无法通信,系统可能无法保证可用性。
2.多主复制:在多主复制架构中,每个节点都可以处理写操作,并将写操作复制到其他节点。这种架构通常更关注可用性,但在网络分区时可能会出现不一致的情况。

NoSQL与CAP理论的关系:

NoSQL 数据库与 CAP 理论紧密相关,因为它们通常用于构建分布式系统。NoSQL 数据库的设计也通常需要在 CAP 理论的三个特性(一致性、可用性、分区容错性)之间做出权衡,以满足特定的应用场景和需求。

1
2
3
4
5
6
7
8
9
CP 类型(Consistency + Partition Tolerance) :
特点:优先保证一致性和分区容错性,在网络分区期间可能牺牲可用性。
示例:一些强一致性需求的 NoSQL 数据库,如某些场景下的 MongoDB(当配置为强一致性时)。在遇到网络分区时,MongoDB 的部分节点可能会不可用,以确保数据的一致性。

AP 类型(Availability + Partition Tolerance) :
特点:优先保证可用性和分区容错性,在网络分区期间可能牺牲一致性。
示例:Cassandra 是一个典型的 AP 型 NoSQL 数据库。它设计用于高可用性,在网络分区期间仍然允许读写操作,但可能会返回过时的数据。

网络分区是指在分布式系统中,由于网络故障、配置错误或其他原因,导致系统中的一部分节点无法与另一部分节点进行通信。

网络分区后,AP导致的数据不一致在,网络恢复后,数据怎么办?

1
2
3
4
5
6
7
8
9
10
11
12
1.数据同步机制
-主动同步:在网络恢复后,系统会自动检测到网络分区的解除,并启动数据同步过程。各个节点会将自己在网络分区期间修改的数据发送给其他节点,以保证数据的一致性。例如,Cassandra 会记录每个节点的写操作,并在网络恢复后自动同步。
-定期同步:系统会定期检查各个节点的数据版本或时间戳,发现不一致时进行同步。这种方式可以确保即使网络分区导致的数据不一致,也能在一定时间内得到修复。
2.冲突解决机制
-版本号比较:每个数据项都附带一个版本号,网络分区期间各个节点独立修改数据时会增加版本号。在网络恢复后,比较数据的版本号,保留最高版本号的数据,或者将不同版本的数据合并。
-时间戳机制:记录数据最后更新的时间戳,网络恢复后以时间戳较新的数据为准。需要注意的是,时间戳机制依赖于各个节点的时间同步,如果节点时间不同步,可能会导致错误的判断。
-业务规则:根据业务逻辑来解决数据冲突。例如,在一个电商系统的购物车数据中,如果两个节点在网络分区期间都添加了商品,网络恢复后可以根据业务规则(如合并购物车商品)来解决冲突。
3.人工干预
-日志审计:系统会记录网络分区期间的所有操作日志。网络恢复后,通过人工审计日志来发现和解决数据不一致的问题。
-数据校验:定期进行数据校验,发现不一致时手动修复。这种方式通常适用于对数据一致性要求极高且自动冲突解决机制无法保证正确性的场景。
4.最终一致性模型
-网络分区期间:允许数据不一致,但保证网络恢复后数据最终会达到一致状态。例如,使用消息队列来缓冲网络分区期间的写操作,网络恢复后,消息队列中的操作会被依次执行,确保数据最终一致。

主从复制

基本原理

基本原则

最大问题

延时

一主一从常见配置

分布式数据库服务器的四层架构:

访问层:接收访问信息并按负荷智能的分配给中转服务器,接受数据结果并返回客户端。

中转层:接收访问服务器发来的数据访问指令,从总储存服务器寻找数据分布所在的储存服务器,发送指令。

表头层:储存数据的表头信息,以确定储存服务器位置。

处理层:分布式数据储存服务器,接收指令并执行,然后返回数据给访问服务器。

https://www.cnblogs.com/dawnstar/p/5054136.html

mysql版本一致且后台以服务运行(最少此次本号要一致)->ip地址不同,各自中ping一下对方地址-> 根据文件修改(server-id=1注释,server-id=2开启)->从机的mysql重启

在windows主机上建立账户并授权slave

1
2
3
4
5
grant replication slave on *.* to 'zhangsan'@'从机数据库ip' identified by '123456';
授权 复制 从机以 zhansan的用户名和123456的密码登录主机
登录mysql中复制入上面代码
flush privileges刷新命令
show master status;查看主机状态

File(二进制日志文件)

Position(位置)

Binlog_Do_DB需要复制的数据库(没写,代表之后新建的数据库都要复制)

Binlog_Ignore_DB不需要复制的数据库

从机从二进制日志文件mysqlbin.000035的第341开始抄

在linux从机上配置需要复制的主机

1
2
3
4
5
6
7
change master to master_host='主机ip',
master_user='zhansan',master_password='123456',
master_log_file='file名字',master_log_pos=position数字;
linux登录mysql,复制入上面代码
start slave;启动从服务器复制功能
show slave status\G
执行后下图2个yes必须存在!否则不会成功

尝试:主机新建库、新建表、insert记录,从机复制

如何停止从服务复制功能(有时候主机的数据,从机不需要,这时用到,以及以下情况)

每次从来需要主机show master status,因为position不一样

MySQL缓存机制

MySQL 有多种缓存机制,包括查询缓存、InnoDB 的缓冲池、MyISAM 的键缓存等。

查询缓存

1
2
-工作原理:查询缓存会将客户端的查询请求和服务器返回的结果集存储在内存中。当相同的查询再次执行时,MySQL 可以直接从查询缓存中返回结果,而无需再次访问数据表。
-限制:如果数据表发生更改(如插入、更新或删除操作),与该表相关的查询缓存将被自动失效,后续的查询需要重新从数据表中获取数据。

InnoDB 缓冲池

1
2
- 工作原理:InnoDB 使用缓冲池来缓存数据和索引页。当读取数据时,InnoDB 会优先从缓冲池中获取数据,如果数据不在缓冲池中,才会从磁盘读取并加载到缓冲池中。
- 持久性:缓冲池中的数据会在内存中保留,直到被其他数据替换或 MySQL 服务器重启。

MyISAM 的键缓存

1
-工作原理:MyISAM 使用键缓存(Key Buffer)来缓存索引块。数据文件的读取直接从磁盘进行,而不经过缓存。

实际应用场景

1
2
- 查询缓存默认关闭:从 MySQL 8.0 开始,默认情况下查询缓存是关闭的,因为它在某些情况下可能会降低性能。
- 手动控制缓存:可以通过配置参数手动开启或关闭查询缓存,并设置缓存的大小。