MySQL中隔离级别RC与RR的区别及说明

目录
  • MySQL隔离级别RC与RR的区别
  • MySQL8 RC和RR隔离级别的实战
    • 一、创建测试数据
    • 二、RR隔离级别
    • 三、RC隔离级别

MySQL隔离级别RC与RR的区别

RR 支持 gap lock(next-key lock),而RC则没有gap lock。因为MySQL的RR需要gap lock来解决幻读问题。而RC隔离级别则是允许存在不可重复读和幻读的。所以RC的并发一般要好于RR;

RC 隔离级别,通过 where 条件走非索引列过滤之后,不符合条件的记录上的行锁,会释放掉(虽然这里破坏了“两阶段加锁原则”);但是RR隔离级别,通过 where 条件走非索引列过滤之后,即使不符合where条件的记录,也是会加行锁。所以从锁方面来看,RC的并发应该要好于RR;可以减少一部分锁竞争,减少死锁和锁超时的概率。

RC 隔离级别不支持 statement 格式的bin log,因为该格式的复制,会导致主从数据的不一致;只能使用 mixed 或者 row 格式的bin log; 这也是为什么MySQL默认使用RR隔离级别的原因。复制时,我们最好使用:binlog_format=row

MySQL5.6 的早期版本,RC隔离级别是可以设置成使用statement格式的bin log,后期版本则会直接报错;

简单而且,RC隔离级别时,事务中的每一条select语句会读取到他自己执行时已经提交了的记录,也就是每一条select都有自己的一致性读ReadView; 而RR隔离级别时,事务中的一致性读的ReadView是以第一条select语句的运行时,作为本事务的一致性读snapshot的建立时间点的。只能读取该时间点之前已经提交的数据。

MySQL8 RC和RR隔离级别的实战

读未提交:在读未提交这个隔离级别下,即使别的事务所做的修改并未提交,也能看到其修改的数据。当事务的隔离级别处于“读未提交”时,其并发性能是最强的,但是隔离性与安全性是最差的,会出现脏读,在生产环境中不使用。

读已提交:读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。该隔离级别避免了脏读,但是却可能出现不可重复读。例如,事务A事先读取了数据,事务B紧接着更新并提交了事务,当事务A再次读取该数据时数据已经发生改变。

可重复读:是指在一个事务内多次读同一数据。假设在一个事务还没结束时,另一个事务也访问同一数据,那么在第一个事务中的两次读数据之间,即使第二个事务对数据进行了修改,第一个事务两次读到的数据也是一样的。这样在一个事务内两次读到的数据就是一样的,因此称为可重复读。读取数据的事务禁止写事务(但允许读事务),写事务则禁止任何其他事务,这样即可避免不可重复读和脏读,但是有时可能出现幻读。

序列化:提供严格的事务隔离。它要求事务序列化执行,即事务只能一个接着一个地执行,但不能并发执行。仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也最高,性能很低,一般很少使用。在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读、还避免了幻读

一、创建测试数据

创建测试表:

create table a (id int auto_increment,
a varchar(10),
b varchar(10),
c varchar(10),
d varchar(10),
 primary key(id) )  engine=INNODB  default charset=utf8;

插入数据

insert into a(a,b,c,d) 
values 
('1','1','1','1'),
('2','2','2','2'),
('3','3','3','3'),
('4','4','4','4'),
('5','5','5','5'),
('6','6','6','6');

查询数据:

mysql> select * from a;
+----+------+------+------+------+
| id | a    | b    | c    | d    |
+----+------+------+------+------+
|  1 | 1    | 1    | 1    | 1    |
|  2 | 2    | 2    | 2    | 2    |
|  3 | 3    | 3    | 3    | 3    |
|  4 | 4    | 4    | 4    | 4    |
|  5 | 5    | 5    | 5    | 5    |
|  6 | 6    | 6    | 6    | 6    |
+----+------+------+------+------+
6 rows in set (0.00 sec)

创建索引:

CREATE INDEX index_b_c ON a(b,c);

二、RR隔离级别

mysql> show variables like '%iso%';
+-----------------------+-----------------+
| Variable_name         | Value           |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.00 sec)

可以从上图看出,目前MySQL处于RR的隔离级别(可重复读)

事务1:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update a set d='20' where a='1';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

事务2:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update a set d='20' where a='2';#一直等待,最后报错
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

等待时间取决于这个参数:

innodb_lock_wait_timeout

查看mysql锁情况:

PS:因为show processlist只会显示出当前正在执行的语句,有些语句很快就执行完成了,所以有时候是看不全的,需要通过系统表查看

performance_schema.data_locks

mysql> select * from performance_schema.data_locks;
+--------+---------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+-----------+-------------+------------------------+
| ENGINE | ENGINE_LOCK_ID                        | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE | LOCK_STATUS | LOCK_DATA              |
+--------+---------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+-----------+-------------+------------------------+
| INNODB | 140166601014432:1066:140166526246928  |                 14257 |       108 |       11 | test          | a           | NULL           | NULL              | NULL       |       140166526246928 | TABLE     | IX        | GRANTED     | NULL                   |
| INNODB | 140166601014432:5:4:8:140166526244128 |                 14257 |       108 |       11 | test          | a           | NULL           | NULL              | PRIMARY    |       140166526244128 | RECORD    | X         | WAITING     | 1                      |
| INNODB | 140166601010392:1066:140166526216544  |                 14256 |        76 |       73 | test          | a           | NULL           | NULL              | NULL       |       140166526216544 | TABLE     | IX        | GRANTED     | NULL                   |
| INNODB | 140166601010392:5:4:1:140166526213552 |                 14256 |        76 |       73 | test          | a           | NULL           | NULL              | PRIMARY    |       140166526213552 | RECORD    | X         | GRANTED     | supremum pseudo-record |
| INNODB | 140166601010392:5:4:3:140166526213552 |                 14256 |        76 |       73 | test          | a           | NULL           | NULL              | PRIMARY    |       140166526213552 | RECORD    | X         | GRANTED     | 2                      |
| INNODB | 140166601010392:5:4:4:140166526213552 |                 14256 |        76 |       73 | test          | a           | NULL           | NULL              | PRIMARY    |       140166526213552 | RECORD    | X         | GRANTED     | 3                      |
| INNODB | 140166601010392:5:4:5:140166526213552 |                 14256 |        76 |       73 | test          | a           | NULL           | NULL              | PRIMARY    |       140166526213552 | RECORD    | X         | GRANTED     | 4                      |
| INNODB | 140166601010392:5:4:6:140166526213552 |                 14256 |        76 |       73 | test          | a           | NULL           | NULL              | PRIMARY    |       140166526213552 | RECORD    | X         | GRANTED     | 5                      |
| INNODB | 140166601010392:5:4:7:140166526213552 |                 14256 |        76 |       73 | test          | a           | NULL           | NULL              | PRIMARY    |       140166526213552 | RECORD    | X         | GRANTED     | 6                      |
| INNODB | 140166601010392:5:4:8:140166526213552 |                 14256 |        76 |       73 | test          | a           | NULL           | NULL              | PRIMARY    |       140166526213552 | RECORD    | X         | GRANTED     | 1                      |
+--------+---------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+-----------+-------------+------------------------+
10 rows in set (0.00 sec)

information_schema.INNODB_TRX

mysql> select * from INNODB_TRX\G
*************************** 1. row ***************************
                    trx_id: 14257
                 trx_state: LOCK WAIT
               trx_started: 2022-04-23 17:09:05
     trx_requested_lock_id: 140166601014432:5:4:8:140166526244128
          trx_wait_started: 2022-04-23 17:09:05
                trx_weight: 2
       trx_mysql_thread_id: 51
                 trx_query: update a set d='20' where a='2'
       trx_operation_state: starting index read
         trx_tables_in_use: 1
         trx_tables_locked: 1
          trx_lock_structs: 2
     trx_lock_memory_bytes: 1128
           trx_rows_locked: 1
         trx_rows_modified: 0
   trx_concurrency_tickets: 0
       trx_isolation_level: REPEATABLE READ
         trx_unique_checks: 1
    trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
 trx_adaptive_hash_latched: 0
 trx_adaptive_hash_timeout: 0
          trx_is_read_only: 0
trx_autocommit_non_locking: 0
       trx_schedule_weight: 1
*************************** 2. row ***************************
                    trx_id: 14256
                 trx_state: RUNNING
               trx_started: 2022-04-23 17:07:20
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 3
       trx_mysql_thread_id: 26
                 trx_query: NULL
       trx_operation_state: NULL
         trx_tables_in_use: 0
         trx_tables_locked: 1
          trx_lock_structs: 2
     trx_lock_memory_bytes: 1128
           trx_rows_locked: 7
         trx_rows_modified: 1
   trx_concurrency_tickets: 0
       trx_isolation_level: REPEATABLE READ
         trx_unique_checks: 1
    trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
 trx_adaptive_hash_latched: 0
 trx_adaptive_hash_timeout: 0
          trx_is_read_only: 0
trx_autocommit_non_locking: 0
       trx_schedule_weight: NULL
2 rows in set (0.00 sec)

从这里可以看到,事务ID14256正在运行。

performance_schema .data_lock_waits

mysql> select * from data_lock_waits\G
*************************** 1. row ***************************
                          ENGINE: INNODB
       REQUESTING_ENGINE_LOCK_ID: 140166601014432:5:4:8:140166526244128
REQUESTING_ENGINE_TRANSACTION_ID: 14257
            REQUESTING_THREAD_ID: 108
             REQUESTING_EVENT_ID: 11
REQUESTING_OBJECT_INSTANCE_BEGIN: 140166526244128
         BLOCKING_ENGINE_LOCK_ID: 140166601010392:5:4:8:140166526213552
  BLOCKING_ENGINE_TRANSACTION_ID: 14256
              BLOCKING_THREAD_ID: 76
               BLOCKING_EVENT_ID: 73
  BLOCKING_OBJECT_INSTANCE_BEGIN: 140166526213552
1 row in set (0.00 sec)

从这里可以看到,因为14256事务ID阻塞了当前这个事务。

从这三张图可以看出来,第一个事务正在执行(还没commit),第二个事务的update处于锁等待状态,可能有小伙伴会说,mysql不是行级锁吗?为什么update的不是同一条数据,还是会锁全表呢?

带着这个疑问我们来看,下面来看第二个例子:

开启第一个事务:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update a set d='20' where b='2'; 
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

开启第二个事务:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update a set d='20' where b='3'; 
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

思考:为什么这个语句就可以执行成功呢?

查看mysql锁情况:

performance_schema.data_locks
mysql> select * from performance_schema.data_locks;
+--------+----------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+-------------+
| ENGINE | ENGINE_LOCK_ID                         | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE     | LOCK_STATUS | LOCK_DATA   |
+--------+----------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+-------------+
| INNODB | 140166601010392:1066:140166526216544   |                 14266 |       110 |       11 | test          | a           | NULL           | NULL              | NULL       |       140166526216544 | TABLE     | IX            | GRANTED     | NULL        |
| INNODB | 140166601010392:5:5:3:140166526213552  |                 14266 |       110 |       11 | test          | a           | NULL           | NULL              | index_b_c  |       140166526213552 | RECORD    | X             | GRANTED     | '2', '2', 2 |
| INNODB | 140166601010392:5:4:11:140166526213896 |                 14266 |       110 |       11 | test          | a           | NULL           | NULL              | PRIMARY    |       140166526213896 | RECORD    | X,REC_NOT_GAP | GRANTED     | 2           |
| INNODB | 140166601010392:5:5:4:140166526214240  |                 14266 |       110 |       11 | test          | a           | NULL           | NULL              | index_b_c  |       140166526214240 | RECORD    | X,GAP         | GRANTED     | '3', '3', 3 |
+--------+----------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+-------------+
4 rows in set (0.00 sec)

information_schema.INNODB_TRX

mysql> select * from INNODB_TRX\G
*************************** 1. row ***************************
                    trx_id: 14267
                 trx_state: RUNNING
               trx_started: 2022-04-23 17:35:44
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 5
       trx_mysql_thread_id: 51
                 trx_query: NULL
       trx_operation_state: NULL
         trx_tables_in_use: 0
         trx_tables_locked: 1
          trx_lock_structs: 4
     trx_lock_memory_bytes: 1128
           trx_rows_locked: 3
         trx_rows_modified: 1
   trx_concurrency_tickets: 0
       trx_isolation_level: REPEATABLE READ
         trx_unique_checks: 1
    trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
 trx_adaptive_hash_latched: 0
 trx_adaptive_hash_timeout: 0
          trx_is_read_only: 0
trx_autocommit_non_locking: 0
       trx_schedule_weight: NULL
*************************** 2. row ***************************
                    trx_id: 14266
                 trx_state: RUNNING
               trx_started: 2022-04-23 17:30:50
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 5
       trx_mysql_thread_id: 53
                 trx_query: NULL
       trx_operation_state: NULL
         trx_tables_in_use: 0
         trx_tables_locked: 1
          trx_lock_structs: 4
     trx_lock_memory_bytes: 1128
           trx_rows_locked: 3
         trx_rows_modified: 1
   trx_concurrency_tickets: 0
       trx_isolation_level: REPEATABLE READ
         trx_unique_checks: 1
    trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
 trx_adaptive_hash_latched: 0
 trx_adaptive_hash_timeout: 0
          trx_is_read_only: 0
trx_autocommit_non_locking: 0
       trx_schedule_weight: NULL
2 rows in set (0.00 sec)

两个事务都在正常运行,互不干扰。

performance_schema.data_lock_waits

mysql> select * from performance_schema.data_lock_waits\G
Empty set (0.00 sec)

锁不存在

事务1提交:

mysql> commit;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from a;
+----+------+------+------+------+
| id | a    | b    | c    | d    |
+----+------+------+------+------+
|  1 | 1    | 1    | 1    | 1    |
|  2 | 2    | 2    | 2    | 20   |
|  3 | 3    | 3    | 3    | 3    |
|  4 | 4    | 4    | 4    | 4    |
|  5 | 5    | 5    | 5    | 5    |
|  6 | 6    | 6    | 6    | 6    |
+----+------+------+------+------+
6 rows in set (0.00 sec)

从这里可以看出,因为事务2并没有提交,所以b=3的数据并没有更新

事务2提交:

mysql> commit;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from a;
+----+------+------+------+------+
| id | a    | b    | c    | d    |
+----+------+------+------+------+
|  1 | 1    | 1    | 1    | 1    |
|  2 | 2    | 2    | 2    | 20   |
|  3 | 3    | 3    | 3    | 20   |
|  4 | 4    | 4    | 4    | 4    |
|  5 | 5    | 5    | 5    | 5    |
|  6 | 6    | 6    | 6    | 6    |
+----+------+------+------+------+
6 rows in set (0.00 sec)

结论

当字段没有建立索引的时候,该字段作为update条件的话,会锁全表。

三、RC隔离级别

设置隔离级别为RC

mysql> set global transaction_isolation='read-committed'

事务1:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update a set d='10' where a='1';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

事务2:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update a set d='20' where a='2';   
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> select* from a;
+----+------+------+------+------+
| id | a    | b    | c    | d    |
+----+------+------+------+------+
|  1 | 1    | 1    | 1    | 1    |
|  2 | 2    | 2    | 2    | 20   |
|  3 | 3    | 3    | 3    | 3    |
|  4 | 4    | 4    | 4    | 4    |
|  5 | 5    | 5    | 5    | 5    |
|  6 | 6    | 6    | 6    | 6    |
+----+------+------+------+------+
#此时事务1执行commit操作
mysql> select * from a;
+----+------+------+------+------+
| id | a    | b    | c    | d    |
+----+------+------+------+------+
|  1 | 1    | 1    | 1    | 10   |
|  2 | 2    | 2    | 2    | 20   |
|  3 | 3    | 3    | 3    | 3    |
|  4 | 4    | 4    | 4    | 4    |
|  5 | 5    | 5    | 5    | 5    |
|  6 | 6    | 6    | 6    | 6    |
+----+------+------+------+------+
6 rows in set (0.00 sec)

在RC隔离级别下,并没有锁表,可以看到,事务1在commit情况下,事务2立刻就可以看到事务1更新的数据,这就是不可重复读。

mysql> select * from performance_schema.data_locks;
+--------+----------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+-----------+
| ENGINE | ENGINE_LOCK_ID                         | ENGINE_TRANSACTION_ID | THREAD_ID | EVENT_ID | OBJECT_SCHEMA | OBJECT_NAME | PARTITION_NAME | SUBPARTITION_NAME | INDEX_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_MODE     | LOCK_STATUS | LOCK_DATA |
+--------+----------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+-----------+
| INNODB | 140166601010392:1067:140166526216544   |                 14315 |       112 |       22 | test          | a           | NULL           | NULL              | NULL       |       140166526216544 | TABLE     | IX            | GRANTED     | NULL      |
| INNODB | 140166601010392:6:4:10:140166526213552 |                 14315 |       112 |       22 | test          | a           | NULL           | NULL              | PRIMARY    |       140166526213552 | RECORD    | X,REC_NOT_GAP | GRANTED     | 1         |
+--------+----------------------------------------+-----------------------+-----------+----------+---------------+-------------+----------------+-------------------+------------+-----------------------+-----------+---------------+-------------+-----------+
2 rows in set (0.00 sec)
mysql> select * from INNODB_TRX\G
*************************** 1. row ***************************
                    trx_id: 14316
                 trx_state: RUNNING
               trx_started: 2022-04-23 18:08:55
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 3
       trx_mysql_thread_id: 57
                 trx_query: NULL
       trx_operation_state: NULL
         trx_tables_in_use: 0
         trx_tables_locked: 1
          trx_lock_structs: 2
     trx_lock_memory_bytes: 1128
           trx_rows_locked: 2
         trx_rows_modified: 1
   trx_concurrency_tickets: 0
       trx_isolation_level: READ COMMITTED
         trx_unique_checks: 1
    trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
 trx_adaptive_hash_latched: 0
 trx_adaptive_hash_timeout: 0
          trx_is_read_only: 0
trx_autocommit_non_locking: 0
       trx_schedule_weight: NULL
*************************** 2. row ***************************
                    trx_id: 14315
                 trx_state: RUNNING
               trx_started: 2022-04-23 18:08:04
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 3
       trx_mysql_thread_id: 55
                 trx_query: NULL
       trx_operation_state: NULL
         trx_tables_in_use: 0
         trx_tables_locked: 1
          trx_lock_structs: 2
     trx_lock_memory_bytes: 1128
           trx_rows_locked: 1
         trx_rows_modified: 1
   trx_concurrency_tickets: 0
       trx_isolation_level: READ COMMITTED
         trx_unique_checks: 1
    trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
 trx_adaptive_hash_latched: 0
 trx_adaptive_hash_timeout: 0
          trx_is_read_only: 0
trx_autocommit_non_locking: 0
       trx_schedule_weight: NULL
2 rows in set (0.00 sec)

两个事务都正常运行。

mysql> select * from data_lock_waits\G
Empty set (0.00 sec)

并没有锁表

结论:RC隔离级别下,其实是顺序的给每一行都加了锁的(不是update的数据的话,就马上解开),但是速度非常快,如果数据量足够大的话,也是会有lock的。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 深入理解MySQL事务的4种隔离级别

    目录 1 简介 2 什么是数据库事务? 2.1 事务的四大特性(ACID) 3 并发事务会导致的问题 3.1 本文会使用到的 SQL 语句 3.1.1 示例表结构 3.1.2 查询事务的默认隔离级别 3.1.3 设置当前会话的事务隔离级别 4 事务的4种隔离级别和示例演示 4.1 读未提交 4.2 读已提交 4.3 可重复读 4.4 串行化 1 简介 事务的4种隔离级别分别是读未提交(Read Uncommitted).读已提交(Read Committed). 可重复读(Repeatable

  • mysql数据库隔离级别详解

    目录 隔离级别 一.mysql有四个事务隔离级别 二.为什么默认RR隔离级别? 三.RR隔离级别下手动加锁解决幻读理论基础 脏读.不可重复读.幻读 及其解决方法 事务隔离级别命令行操作 操作验证 一.实现脏读 二.操作验证--实现不可重复读 三.操作验证--解决不可重复读 四.操作验证--实现幻读 总结 隔离级别 一.mysql有四个事务隔离级别 每个级别都有字符或数字编号 读未提交 READ UNCOMMITTED | 0 : 存在脏读,不可重复度,幻读的问题. 读已提交 READ COMMI

  • 浅析MySQL如何实现事务隔离

    一.前言 众所周知,MySQL的在RR隔离级别下查询数据,是可以保证数据不受其它事物影响,而在RC隔离级别下只要其它事物commit后,数据都会读到commit之后的数据,那么事物隔离的原理是什么?是通过什么实现的呢?那肯定是通过MVCC机制(Multi-Version Concurrency Control,即多版本并发控制). 注:MySQL的InnoDB引擎之所以能够支持高性能的并发性能,就是由于MySQL的MVCC机制(归功于undo log.Read-View.),但是本篇不对MVCC

  • 详解MySQL中事务隔离级别的实现原理

    前言 说到数据库事务,大家脑子里一定很容易蹦出一堆事务的相关知识,如事务的ACID特性,隔离级别,解决的问题(脏读,不可重复读,幻读)等等,但是可能很少有人真正的清楚事务的这些特性又是怎么实现的,为什么要有四个隔离级别. 今天我们就先来聊聊MySQL中事务的隔离性的实现原理,后续还会继续出文章分析其他特性的实现原理. 当然MySQL博大精深,文章疏漏之处在所难免,欢迎批评指正. 说明 MySQL的事务实现逻辑是位于引擎层的,并且不是所有的引擎都支持事务的,下面的说明都是以InnoDB引擎为基准.

  • MySQL中隔离级别RC与RR的区别及说明

    目录 MySQL隔离级别RC与RR的区别 MySQL8 RC和RR隔离级别的实战 一.创建测试数据 二.RR隔离级别 三.RC隔离级别 MySQL隔离级别RC与RR的区别 RR 支持 gap lock(next-key lock),而RC则没有gap lock.因为MySQL的RR需要gap lock来解决幻读问题.而RC隔离级别则是允许存在不可重复读和幻读的.所以RC的并发一般要好于RR: RC 隔离级别,通过 where 条件走非索引列过滤之后,不符合条件的记录上的行锁,会释放掉(虽然这里破

  • Mysql事务隔离级别之读提交详解

    查看mysql 事务隔离级别 mysql> show variables like '%isolation%'; +---------------+----------------+ | Variable_name | Value | +---------------+----------------+ | tx_isolation | READ-COMMITTED | +---------------+----------------+ 1 row in set (0.00 sec) 可以看到

  • 详解MySQL 数据库隔离级别与MVCC

    Mysql是我们日常生产与学习中最常接触到的数据库之一,今天讲一讲在Mysql(或者说其他类似的数据库)中存在的隔离级别以及用来提高效率的多版本并发控制(MVCC). 一.隔离级别 首先我们需要提到一个概念:事务.什么是事务?事务就是完成一个基础操作的一系列操作语句的一个集合.例如我要将200元从账户A转移到账户B,那么我可能会进行一下的操作: a.验证账户A中的余额是否大于200元. b.将账户A中的余额减200元. c.将账户B中的余额加200元. 我们就将上面的abc三个操作成为一个事务.

  • 深入理解Mysql事务隔离级别与锁机制问题

    概述 数据库一般都会并发执行多个事务,多个事务可能会并发的对相同的一批数据进行增删改查操作,可能导致脏读.脏写.不可重复度和幻读.这些问题的本质都是数据库的多事务并发问题,为了解决事务并发问题,数据库设计了事务隔离机制.锁机制.MVCC多版本并发控制隔离机制,用一整套机制来解决多事务并发问题. 事务及其ACID属性 原子性:操作的不可分割: 一致性:数据的一致性: 隔离性:事务之间互不干扰: 持久性:数据的修改时永久的: 并发事务处理带来的问题 脏写:丢失更新,最后的更新覆盖了由其他事务所做的更

  • mysql事务隔离级别详情

    serializable 串行化(无问题) 事务必须以顺序的方式执行,前一个事务提交之前后面的事务无法进行提交,最安全,但是不能并发操作,导致效率低下. repeatab read 可重复读(默认隔离级别)(幻读) 在一个事务未提交之前,里面不论执行多少次查询,查询的结果都一样(即使这条记录被别的事务修改过)但是可能会出现幻读 read committed 读已提交(不可重复度,幻读) 在当前事务中别的事务提交的数据可以看到,那么可能会导致不可重复读(另一个线程提交数据后当前线程可以看到,然后就

  • 一文了解MySQL事务隔离级别

    目录 前言 1.四种事务隔离级别 1.1 READ UNCOMMITTED 1.2 READ COMMITTED 1.3 REPEATABLE READ 1.4 SERIALIZABLE 1.5 小结 2.并发事务中的问题 2.1 脏读 2.2 不可重复读 2.3 幻读 3.隔离级别实战 3.1 查询事务隔离级别 3.2 设置事务隔离级别 3.3 脏读问题 3.4 不可重复读问题 3.5 幻读问题 总结 前言 MySQL 事务隔离级别是为了解决并发事务互相干扰的问题的,MySQL 事务隔离级别总

  • 一文详解MySQL不同隔离级别都使用什么锁

    目录 说透 MySQL 锁机制 事务隔离级别 MySQL 锁类型 读未提交 读已提交 可重复读 总结 在上篇文章,我们聊了「MySQL 啥时候会用表锁,啥时候用行锁」这个问题.在文章中,我们还留了一个问题,即:如果查询或更新时的数据特别多,是否从行锁会升级为表锁? 此外,还有朋友留言说到:不同的隔离级别可能会用不同的锁,可以结合隔离级别来聊聊.其实上面虽然是两个问题,但如果你把不同隔离级别下的加锁问题搞清楚了,那么第一个问题自然也清楚了. 今天,就让我带着大家来聊聊不同隔离级别下,都会使用什么锁

  • MySQL中create table as 与like的区别分析

    本文分析了MySQL中create table as 与like的区别.分享给大家供大家参考,具体如下: 对于mysql的复制相同表结构方法,有create table as 和create table like 两种,区别是什么呢? 复制代码 代码如下: create table t2 as select * from t1 where 1=2; 或者 复制代码 代码如下: limit 0; as创建出来的t2表(新表)缺少t1表(源表)的索引信息,只有表结构相同,没有索引. 复制代码 代码如

  • MySQL中Decimal类型和Float Double的区别(详解)

    MySQL中存在float,double等非标准数据类型,也有decimal这种标准数据类型. 其区别在于,float,double等非标准类型,在DB中保存的是近似值,而Decimal则以字符串的形式保存数值. float,double类型是可以存浮点数(即小数类型),但是float有个坏处,当你给定的数据是整数的时候,那么它就以整数给你处理.这样我们在存取货币值的时候自然遇到问题,我的default值为:0.00而实际存储是0,同样我存取货币为12.00,实际存储是12. 幸好mysql提供

随机推荐