MYSQL RR隔离级别下无索引更新是否表锁?

最近在MYSQL菜鸟群有群友提问,说他看了某个公众号里面文章说 "MYSQL RR隔离级别下无索引更新会导致表锁! "  他表示疑惑,而且不仅是他,还有很多个她在不同的群里同样表示疑惑!  下面是群友的截图

是啊 MYSQL 以及进化到了8.3.0版本了,普遍都使用5.7和8.0版本.而且还听说 INNODB引擎会把不符合条件的记录给释放锁. 原理大概是这样的,一个表有100行记录,一条UPDATE语句需要更新10行记录. 而这10行记录分散在这100行里, 从第一个符合条件的行到最后一个不符合条件的行 大约是30行. 好吧! 30行和100行差不多. 开始之处不管三七二十一,见行就上X锁.然后把行回传给MYSQL SERVER层,进行过滤处理. 需要的请留下,不需要的通知给INNODB,好让引擎把行锁个释放掉了.

从这个优化理论来说, RR下应该会把不需要的记录给释放掉,那么RR下的表锁就不可能出现.

套用某人的话说, 我以上都是胡说八道! 我们试验一把,先看下真正表锁是什么样子!
先上个表读锁

SESSION 2
MySQL 14:52:19 root@192.168.0.221 [dba]>lock tables dba.personal_identity_info read;
Query OK, 0 rows affected (0.01 sec)

我们SESSION 2是主决 SESSION3 负责查看监控, SESSION 1负责打酱油的.

SESSION 3
[sys]>select * from performance_schema.table_handles;
+-------------+---------------+----------------------------+-----------------------+-----------------+----------------+---------------+---------------+
| OBJECT_TYPE | OBJECT_SCHEMA | OBJECT_NAME                | OBJECT_INSTANCE_BEGIN | OWNER_THREAD_ID | OWNER_EVENT_ID | INTERNAL_LOCK | EXTERNAL_LOCK |
+-------------+---------------+----------------------------+-----------------------+-----------------+----------------+---------------+---------------+
| TABLE       | sys           | sys_config                 |       140317340487016 |            NULL |           NULL | NULL          | NULL          |
| TABLE       | dba           | personal_identity_info     |       140317120949096 |             101 |             29 | NULL          | READ EXTERNAL |
+-------------+---------------+----------------------------+-----------------------+-----------------+----------------+---------------+---------------+
235 rows in set (0.01 sec)


MySQL 15:41:03 root@192.168.0.221 [sys]>select * from performance_schema.metadata_locks;
+-------------+--------------------+------------------------+-------------+-----------------------+------------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA      | OBJECT_NAME            | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE        | LOCK_DURATION | LOCK_STATUS | SOURCE            | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------+--------------------+------------------------+-------------+-----------------------+------------------+---------------+-------------+-------------------+-----------------+----------------+
| TABLE       | dba                | personal_identity_info | NULL        |       140316984440272 | SHARED_READ_ONLY | TRANSACTION   | GRANTED     | sql_parse.cc:5768 |             105 |             29 |
| TABLE       | performance_schema | metadata_locks         | NULL        |       140316917412768 | SHARED_READ      | TRANSACTION   | GRANTED     | sql_parse.cc:5768 |             104 |             48 |
+-------------+--------------------+------------------------+-------------+-----------------------+------------------+---------------+-------------+-------------------+-----------------+----------------+
2 rows in set (0.00 sec)

从TABLE_HANDLES说personal_identity_info是外部锁 READ EXTERNAL.
从metadata_locks 表看SHARED_READ_ONLY 共享只读锁
下面更新其它行,打酱油的试图更新且等待中

SESSION 1
MySQL 15:00:22 root@192.168.0.221 [dba]>update dba.personal_identity_info set surname='曾' where surname='曾君';
ERROR 4031 (HY000): The client was disconnected by the server because of inactivity. See wait_timeout and interactive_timeout for configuring this behavior.
No connection. Trying to reconnect...
Connection id:    60
Current database: dba
SESSION 3

MySQL 15:41:23 root@192.168.0.221 [sys]>SELECT PROCESSLIST_ID,THREAD_OS_ID,THREAD_ID,PROCESSLIST_INFO FROM performance_schema.threads where TYPE='FOREGROUND';
+----------------+--------------+-----------+-----------------------------------------------------------------------------------------------------------------------+
| PROCESSLIST_ID | THREAD_OS_ID | THREAD_ID | PROCESSLIST_INFO                                                                                                      |
+----------------+--------------+-----------+-----------------------------------------------------------------------------------------------------------------------+
|              5 |         6440 |        45 | NULL                                                                                                                  |
|              7 |         6444 |        49 | NULL                                                                                                                  |
|             34 |         6480 |        80 | NULL                                                                                                                  |
|             35 |         6566 |        81 | NULL                                                                                                                  |
|             49 |         6607 |        95 | NULL                                                                                                                  |
|             57 |         7822 |       103 | NULL                                                                                                                  |
|             58 |         6454 |       104 | SELECT PROCESSLIST_ID,THREAD_OS_ID,THREAD_ID,PROCESSLIST_INFO FROM performance_schema.threads where TYPE='FOREGROUND' |
|             59 |         6479 |       105 | NULL                                                                                                                  |
|             60 |         7823 |       106 | update dba.personal_identity_info set surname='曾' where surname='曾君'                                               |
+----------------+--------------+-----------+-----------------------------------------------------------------------------------------------------------------------+
9 rows in set (0.00 sec)


MySQL 15:44:41 root@192.168.0.221 [sys]> select * from performance_schema.metadata_locks where owner_thread_Id != sys.ps_thread_id(connection_id());
+-------------+---------------+------------------------+-------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA | OBJECT_NAME            | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE           | LOCK_DURATION | LOCK_STATUS | SOURCE            | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------+---------------+------------------------+-------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
| TABLE       | dba           | personal_identity_info | NULL        |       140316984440272 | SHARED_READ_ONLY    | TRANSACTION   | GRANTED     | sql_parse.cc:5768 |             105 |             29 |
| GLOBAL      | NULL          | NULL                   | NULL        |       140317857342752 | INTENTION_EXCLUSIVE | STATEMENT     | GRANTED     | sql_base.cc:3038  |             106 |             23 |
| TABLE       | dba           | personal_identity_info | NULL        |       140317856664544 | SHARED_WRITE        | TRANSACTION   | PENDING     | sql_parse.cc:5768 |             106 |             23 |
+-------------+---------------+------------------------+-------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
3 rows in set, 1 warning (0.00 sec)

表要上共享写,确被共享度给阻塞了

SESSION 2
UNLOCK TABLES



MySQL 15:58:46 root@192.168.0.221 [sys]>select * from performance_schema.table_handles;
+-------------+---------------+----------------------------+-----------------------+-----------------+----------------+---------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA | OBJECT_NAME                | OBJECT_INSTANCE_BEGIN | OWNER_THREAD_ID | OWNER_EVENT_ID | INTERNAL_LOCK | EXTERNAL_LOCK  |
+-------------+---------------+----------------------------+-----------------------+-----------------+----------------+---------------+----------------+
| TABLE       | sqle          | workflows                  |       140317118649272 |            NULL |           NULL | NULL          | NULL           |
| TABLE       | dba           | personal_identity_info     |       140316984445496 |             105 |         177468 | NULL          | WRITE EXTERNAL |
+-------------+---------------+----------------------------+-----------------------+-----------------+----------------+---------------+----------------+
238 rows in set (0.00 sec)

MySQL 16:01:57 root@192.168.0.221 [sys]>select * from performance_schema.metadata_locks where owner_thread_Id != sys.ps_thread_id(connection_id());
+-------------+---------------+----------------------------+-------------+-----------------------+----------------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA | OBJECT_NAME                | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE            | LOCK_DURATION | LOCK_STATUS | SOURCE            | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------+---------------+----------------------------+-------------+-----------------------+----------------------+---------------+-------------+-------------------+-----------------+----------------+
| GLOBAL      | NULL          | NULL                       | NULL        |       140316984580720 | INTENTION_EXCLUSIVE  | STATEMENT     | GRANTED     | sql_base.cc:5436  |             105 |         176218 |
| SCHEMA      | dba           | NULL                       | NULL        |       140316988086032 | INTENTION_EXCLUSIVE  | TRANSACTION   | GRANTED     | sql_base.cc:5423  |             105 |         176218 |
| TABLE       | dba           | personal_identity_info     | NULL        |       140316984440272 | SHARED_NO_READ_WRITE | TRANSACTION   | GRANTED     | sql_parse.cc:5768 |             105 |         176219 |
| TABLESPACE  | NULL          | dba/personal_identity_info | NULL        |       140316987539760 | INTENTION_EXCLUSIVE  | TRANSACTION   | GRANTED     | lock.cc:802       |             105 |         177465 |
+-------------+---------------+----------------------------+-------------+-----------------------+----------------------+---------------+-------------+-------------------+-----------------+----------------+
4 rows in set (0.00 sec)

释放掉共享读,再上表写锁 出现 WRITE EXTERNAL  SHARED_NO_READ_WRITE;

接下来我们看看RR模式下无索更新是否会出现上面的情况? 这次让SESSION 1当主角,先看执行计划,走主键索引

MySQL 16:04:15 root@192.168.0.221 [dba]>explain update dba.personal_identity_info set surname='王X' where surname='张';
+----+-------------+------------------------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table                  | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+------------------------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
|  1 | UPDATE      | personal_identity_info | NULL       | index | NULL          | PRIMARY | 8       | NULL | 1001 |   100.00 | Using where |
+----+-------------+------------------------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.01 sec)

然后开始SESSION 1 的表演

SESSION 1:

MySQL 14:05:00 root@192.168.0.221 [dba]>show session variables like '%iso%';
+-----------------------+-----------------+
| Variable_name         | Value           |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.01 sec)

MySQL 14:05:56 root@192.168.0.221 [dba]>show global variables like '%iso%';
+-----------------------+-----------------+
| Variable_name         | Value           |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.02 sec)

MySQL 14:06:17 root@192.168.0.221 [dba]>set session sql_safe_updates=off;
Query OK, 0 rows affected (0.00 sec)

MySQL 14:06:37 root@192.168.0.221 [dba]>BEGIN;
Query OK, 0 rows affected (0.00 sec)

MySQL 14:16:58 root@192.168.0.221 [dba]>select * from dba.personal_identity_info where surname='张';
+-----+--------------------+---------+-----------+-------------+-----+---------------------+-----+---------------+-------------+----------------------------+----------------------------+
| id  | identity_number    | surname | name      | mobile      | sex | birthday            | age | top_education | income_year | create_time                | update_time                |
+-----+--------------------+---------+-----------+-------------+-----+---------------------+-----+---------------+-------------+----------------------------+----------------------------+
| 551 | 13.544431931846246 | 张      | 梦冰师    | 13552049405 | 男  | 1970-05-18 00:00:00 |  33 | 初中          |       56482 | 2023-05-18 15:32:12.735522 | 2023-05-18 15:32:12.735522 |
| 800 | 133777832243384635 | 张      | 栋家恩    | 14899421941 | 男  | 1971-05-18 00:00:00 |  49 | 文盲          |       27376 | 2023-05-18 15:32:19.409945 | 2023-05-18 15:32:19.409945 |
| 912 | 13.393129107908466 | 张      | 顺水娜    | 13317756125 | 男  | 1965-05-18 00:00:00 | 127 | 文盲          |       77904 | 2023-05-18 15:32:21.144088 | 2023-05-18 15:32:21.144088 |
+-----+--------------------+---------+-----------+-------------+-----+---------------------+-----+---------------+-------------+----------------------------+----------------------------+
3 rows in set (0.01 sec)

MySQL 14:17:09 root@192.168.0.221 [dba]>update dba.personal_identity_info set surname='王X' where surname='张';
Query OK, 3 rows affected (0.06 sec)
Rows matched: 3  Changed: 3  Warnings: 0

监控SESSION 3 看了它上了好多X索还有 SUPREMUM PSEUNDO-RECORD

SESSION 3
MySQL 14:17:02 root@192.168.0.221 [dba]>SELECT LOCK_TYPE,LOCK_MODE,LOCK_DATA FROM performance_schema.data_locks;
+-----------+-----------+------------------------+
| LOCK_TYPE | LOCK_MODE | LOCK_DATA              |
+-----------+-----------+------------------------+
| TABLE     | IX        | NULL                   |
| RECORD    | X         | supremum pseudo-record |
| RECORD    | X         | 1                      |
| RECORD    | X         | 2                      |
| RECORD    | X         | 3                      |
| RECORD    | X         | 4                      |
| RECORD    | X         | 5                      |
| RECORD    | X         | 6                      |
| RECORD    | X         | 7                      |
| RECORD    | X         | 8                      |
| RECORD    | X         | 9                      |
| RECORD    | X         | 10                     |
| RECORD    | X         | 1000                   |
| RECORD    | X         | 1005                   |
| RECORD    | X         | 1009                   |
| RECORD    | X         | 1008                   |
| RECORD    | X         | 1010                   |
| RECORD    | X         | 1011                   |
| RECORD    | X         | 1012                   |
| RECORD    | X         | 937                    |
| RECORD    | X         | 964                    |
| RECORD    | X         | 969                    |
| RECORD    | X         | 1001                   |
| RECORD    | X         | 912                    |
+-----------+-----------+------------------------+
1018 rows in set (0.03 sec)

AI 3.5 说得差不多

在MySQL中,DATA_LOCK表用于存储由各种锁机制创建的锁信息。LOCK_DATA列中的SUPREMUM PSEUDO-RECORD表示的是一个伪记录,它在内部用于表示一个范围的锁。

具体来说,SUPREMUM PSEUDO-RECORD表示的是一个最大值或者上限,它在锁定范围的最顶部。这种伪记录通常用于表示一个范围锁的起始点或终止点,以便清晰地表示锁定的范围。

在MySQL中,范围锁可以用于锁定一个范围内的数据,而不仅仅是单个行或表。这种锁机制可以在多个会话之间提供更灵活的锁定策略,以确保数据的一致性和完整性。

打酱油的出场.......  舔狗舔到一无所有,直到被拒绝!
 

SESSION 2
MySQL 14:22:12 root@192.168.0.221 [dba]>set session sql_safe_updates=off;
Query OK, 0 rows affected (0.00 sec)

MySQL 14:22:29 root@192.168.0.221 [dba]>update dba.personal_identity_info set surname='曾君' where surname='曾';
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

MySQL 14:24:43 root@192.168.0.221 [dba]>INSERT INTO dba.personal_identity_info (IDENTITY_NUMBER,SURNAME,NAME,MOBILE,SEX,BIRTHDAY,AGE,TOP_EDUCATION,INCOME_YEAR) VALUES(135478728875032375,'燕','燕太杰','13984280466','男','2001-05-18 00:00:00','100','博士','27701');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

没有出现表锁的字样! 

SESSION 3
MySQL 15:53:59 root@192.168.0.221 [sys]>select * from performance_schema.table_handles WHERE OBJECT_NAME='personal_identity_info';
+-------------+---------------+------------------------+-----------------------+-----------------+----------------+---------------+---------------+
| OBJECT_TYPE | OBJECT_SCHEMA | OBJECT_NAME            | OBJECT_INSTANCE_BEGIN | OWNER_THREAD_ID | OWNER_EVENT_ID | INTERNAL_LOCK | EXTERNAL_LOCK |
+-------------+---------------+------------------------+-----------------------+-----------------+----------------+---------------+---------------+
| TABLE       | dba           | personal_identity_info |       140317187639336 |            NULL |           NULL | NULL          | NULL          |
| TABLE       | dba           | personal_identity_info |       140317320812936 |            NULL |           NULL | NULL          | NULL          |
| TABLE       | dba           | personal_identity_info |       140317320824264 |            NULL |           NULL | NULL          | NULL          |
| TABLE       | dba           | personal_identity_info |       140317340006888 |            NULL |           NULL | NULL          | NULL          |
| TABLE       | dba           | personal_identity_info |       140316917541176 |            NULL |           NULL | NULL          | NULL          |
| TABLE       | dba           | personal_identity_info |       140316986582840 |            NULL |           NULL | NULL          | NULL          |
| TABLE       | dba           | personal_identity_info |       140317120949096 |            NULL |           NULL | NULL          | NULL          |
| TABLE       | dba           | personal_identity_info |       140316984445496 |            NULL |           NULL | NULL          | NULL          |
+-------------+---------------+------------------------+-----------------------+-----------------+----------------+---------------+---------------+
8 rows in set (0.00 sec)


MySQL 15:54:06 root@192.168.0.221 [sys]>select * from performance_schema.metadata_locks where owner_thread_Id != sys.ps_thread_id(connection_id());
+-------------+---------------+------------------------+-------------+-----------------------+--------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA | OBJECT_NAME            | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE    | LOCK_DURATION | LOCK_STATUS | SOURCE            | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------+---------------+------------------------+-------------+-----------------------+--------------+---------------+-------------+-------------------+-----------------+----------------+
| TABLE       | dba           | personal_identity_info | NULL        |       140316984580720 | SHARED_WRITE | TRANSACTION   | GRANTED     | sql_parse.cc:5768 |             105 |            849 |
+-------------+---------------+------------------------+-------------+-----------------------+--------------+---------------+-------------+-------------------+-----------------+----------------+
1 row in set (0.00 sec)

小结 
RR 模式下 无索引更新 INNODB 表 走的是主键聚集索引 对所有行加X锁,以及行之间的GAP锁, 且事务提交会被回滚才释放锁. 其实行锁X+GAP锁就是NEXT-KEY锁
再来一张图,会更加让人记忆深刻

RC 模式下

SESSION 1:
set session transaction isolation level read committed;



MySQL 14:39:17 root@192.168.0.221 [dba]>show session variables like '%iso%';
+-----------------------+----------------+
| Variable_name         | Value          |
+-----------------------+----------------+
| transaction_isolation | READ-COMMITTED |
+-----------------------+----------------+
1 row in set (0.01 sec)

MySQL 14:39:46 root@192.168.0.221 [dba]>show global variables like '%iso%';
+-----------------------+-----------------+
| Variable_name         | Value           |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
1 row in set (0.00 sec)

MySQL 14:39:53 root@192.168.0.221 [dba]>BEGIN;
Query OK, 0 rows affected (0.01 sec)

MySQL 14:40:44 root@192.168.0.221 [dba]>update dba.personal_identity_info set surname='王X' where surname='张';
Query OK, 3 rows affected (0.37 sec)
Rows matched: 3  Changed: 3  Warnings: 0

上的锁真少


SESSION 3:
MySQL 14:35:09 root@192.168.0.221 [sys]>SELECT LOCK_TYPE,LOCK_MODE,LOCK_DATA FROM performance_schema.data_locks;
+-----------+---------------+-----------+
| LOCK_TYPE | LOCK_MODE     | LOCK_DATA |
+-----------+---------------+-----------+
| TABLE     | IX            | NULL      |
| RECORD    | X,REC_NOT_GAP | 551       |
| RECORD    | X,REC_NOT_GAP | 800       |
| RECORD    | X,REC_NOT_GAP | 912       |
+-----------+---------------+-----------+
4 rows in set (0.01 sec)

酱油会话 可颜可甜

ESSION 2:
set session transaction isolation level read committed;
set session sql_safe_updates=off;


MySQL 14:42:13 root@192.168.0.221 [dba]>set session transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)

MySQL 14:42:16 root@192.168.0.221 [dba]>set session sql_safe_updates=off;
Query OK, 0 rows affected (0.00 sec)

MySQL 14:42:29 root@192.168.0.221 [dba]>update dba.personal_identity_info set surname='曾君' where surname='曾';
Query OK, 26 rows affected (0.12 sec)
Rows matched: 26  Changed: 26  Warnings: 0

MySQL 14:42:55 root@192.168.0.221 [dba]>INSERT INTO dba.personal_identity_info (IDENTITY_NUMBER,SURNAME,NAME,MOBILE,SEX,BIRTHDAY,AGE,TOP_EDUCATION,INCOME_YEAR) VALUES(135478728875032375,'燕','燕太杰','13984280466','男','2001-05-18 00:00:00','100','博士','27701');
Query OK, 1 row affected (0.37 sec)

没有表锁!

SESSION 3
MySQL 14:44:55 root@192.168.0.221 [sys]>select THREAD_ID,EVENT_NAME,STATE,TRX_ID,ISOLATION_LEVEL,AUTOCOMMIT  FROM performance_schema.events_transactions_current;
+-----------+-------------+-----------+-----------------+-----------------+------------+
| THREAD_ID | EVENT_NAME  | STATE     | TRX_ID          | ISOLATION_LEVEL | AUTOCOMMIT |
+-----------+-------------+-----------+-----------------+-----------------+------------+
|         1 | transaction | COMMITTED | 421796018412648 | REPEATABLE READ | YES        |
|        36 | transaction | COMMITTED | 421796018411608 | REPEATABLE READ | YES        |
|        46 | transaction | COMMITTED | 421796018413688 | REPEATABLE READ | YES        |
|        49 | transaction | COMMITTED | 421796018412648 | REPEATABLE READ | YES        |
|        80 | transaction | COMMITTED | 421796018415768 | REPEATABLE READ | YES        |
|        81 | transaction | COMMITTED | 421796018416808 | REPEATABLE READ | YES        |
|        92 | transaction | COMMITTED | 421796018413688 | REPEATABLE READ | YES        |
|        95 | transaction | COMMITTED | 421796018418888 | REPEATABLE READ | YES        |
|        99 | transaction | ACTIVE    |            NULL | READ COMMITTED  | NO         |
|       100 | transaction | COMMITTED | 421796018417848 | READ COMMITTED  | YES        |
+-----------+-------------+-----------+-----------------+-----------------+------------+
10 rows in set (0.00 sec)


MySQL 14:47:06 root@192.168.0.221 [sys]>select * from performance_schema.metadata_locks ;
+-------------------+--------------------+------------------------+-----------------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE       | OBJECT_SCHEMA      | OBJECT_NAME            | COLUMN_NAME           | OBJECT_INSTANCE_BEGIN | LOCK_TYPE           | LOCK_DURATION | LOCK_STATUS | SOURCE            | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------------+--------------------+------------------------+-----------------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
| TABLE             | performance_schema | metadata_locks         | NULL                  |       140317723039376 | SHARED_READ         | TRANSACTION   | GRANTED     | sql_parse.cc:5768 |              98 |            101 |
| SCHEMA            | performance_schema | NULL                   | NULL                  |       140317724590224 | INTENTION_EXCLUSIVE | TRANSACTION   | GRANTED     | dd_schema.cc:108  |              98 |            101 |
| COLUMN STATISTICS | performance_schema | metadata_locks         | column_name           |       140317725246048 | SHARED_READ         | STATEMENT     | GRANTED     | sql_base.cc:576   |              98 |            102 |
| COLUMN STATISTICS | performance_schema | metadata_locks         | lock_duration         |       140317725390880 | SHARED_READ         | STATEMENT     | GRANTED     | sql_base.cc:576   |              98 |            102 |
| COLUMN STATISTICS | performance_schema | metadata_locks         | lock_status           |       140317722479760 | SHARED_READ         | STATEMENT     | GRANTED     | sql_base.cc:576   |              98 |            102 |
| COLUMN STATISTICS | performance_schema | metadata_locks         | lock_type             |       140317722480144 | SHARED_READ         | STATEMENT     | GRANTED     | sql_base.cc:576   |              98 |            102 |
| COLUMN STATISTICS | performance_schema | metadata_locks         | object_instance_begin |       140317722479968 | SHARED_READ         | STATEMENT     | GRANTED     | sql_base.cc:576   |              98 |            102 |
| COLUMN STATISTICS | performance_schema | metadata_locks         | object_name           |       140317725245648 | SHARED_READ         | STATEMENT     | GRANTED     | sql_base.cc:576   |              98 |            102 |
| COLUMN STATISTICS | performance_schema | metadata_locks         | object_schema         |       140317725245808 | SHARED_READ         | STATEMENT     | GRANTED     | sql_base.cc:576   |              98 |            102 |
| COLUMN STATISTICS | performance_schema | metadata_locks         | object_type           |       140317722784752 | SHARED_READ         | STATEMENT     | GRANTED     | sql_base.cc:576   |              98 |            102 |
| COLUMN STATISTICS | performance_schema | metadata_locks         | owner_event_id        |       140317724827824 | SHARED_READ         | STATEMENT     | GRANTED     | sql_base.cc:576   |              98 |            102 |
| COLUMN STATISTICS | performance_schema | metadata_locks         | owner_thread_id       |       140317724827456 | SHARED_READ         | STATEMENT     | GRANTED     | sql_base.cc:576   |              98 |            102 |
| COLUMN STATISTICS | performance_schema | metadata_locks         | source                |       140317722490432 | SHARED_READ         | STATEMENT     | GRANTED     | sql_base.cc:576   |              98 |            102 |
| TABLE             | dba                | personal_identity_info | NULL                  |       140316917486288 | SHARED_WRITE        | TRANSACTION   | GRANTED     | sql_parse.cc:5768 |              99 |             60 |
+-------------------+--------------------+------------------------+-----------------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
14 rows in set (0.02 sec)

MySQL 14:50:12 root@192.168.0.221 [sys]>select * from performance_schema.table_handles;
+-------------+---------------+----------------------------+-----------------------+-----------------+----------------+---------------+---------------+
| OBJECT_TYPE | OBJECT_SCHEMA | OBJECT_NAME                | OBJECT_INSTANCE_BEGIN | OWNER_THREAD_ID | OWNER_EVENT_ID | INTERNAL_LOCK | EXTERNAL_LOCK |
+-------------+---------------+----------------------------+-----------------------+-----------------+----------------+---------------+---------------+
| TABLE       | sys           | sys_config                 |       140317340487016 |            NULL |           NULL | NULL          | NULL          |
| TABLE       | dba           | personal_identity_info     |       140317340006888 |            NULL |           NULL | NULL          | NULL          |
| TABLE       | dba           | personal_identity_info     |       140316917541176 |            NULL |           NULL | NULL          | NULL          |
| TABLE       | dba           | personal_identity_info     |       140316986582840 |            NULL |           NULL | NULL          | NULL          |
+-------------+---------------+----------------------------+-----------------------+-----------------+----------------+---------------+---------------+

RC 模式下 无表锁,且在事务提交前就释放掉了不符合条件的记录锁

总的来说 RR下无索引更新INNODB引擎的表, 确实是达到表锁的效果.
不过这么说会显得不那么专业,当然忽悠小白,或者是不懂MYSQL的开发人员,还是可以可以的!

如果面对DBA说的话,套用某人的话来说 简直是胡说八道!

思考题:

   RC隔离级别下,这种无索引更新,最后还是会释放掉那些不符合条件的记录.那么在它上锁到释放锁的过程里,时间里,高并发下,或许会阻塞并发. 

那么引擎和服务层是怎么交互的? 按文章头部列子说, 100行,扫描了30行,需要的是10行.  

方式 一
    扫描一行,就返回一行给服务层,然后服务层判断,下达通知,引擎INNODB根据通知判断是继续保持锁,还是释放锁; 然后继续扫描下一行.

方式二
    扫描,扫描,把30行全扫描完后,一次性提交给服务层进行判断,然后再释放锁.

思考题2 
如果是两表关联更新,这时候JOIN_BUFFER参与关联会采用方式一还是方式二?

这些只能有空的时候调试源码可知一二.  
其实大家学会调试源码,就知道真实的情况,就不会被肤浅的人给忽悠了!

最后作为DBA 需要开启 安全更新参数,就是防止无主键,无索引,无LIMIT下DML操作

set global sql_safe_updates=on;

  • 24
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值