字符集为uft8表,修改字段varchar长度锁表分析

字符串的字段是以字节为单位存储的,utf8字符集的表 一个字符需要三个字节,utf8mb4字符集的表 一个字符需要4个字节。对于小于等于255字节以内的长度可以使用一个byte 存储。大于255个字节的长度则需要使用2个byte存储。如果表字段varchar长度从1到85之间变化的话,改字段的存储字节最大也就是255,一个byte足够存储。此时varchar在1到85长度之间变化,是不会锁表的。但是varchar的长度从小于等于85直接修改到大于85的话,此时他的字节数以及大于255了,存储到磁盘需要至少2个byte.此时DDL需要以copy模式,即会锁表,阻塞写操作。

演示如下:

表记录数
root@node04 20:04:  [db_bill]> select count(*) from t_order_bill_detail_change_log
    -> ;
+----------+
| count(*) |
+----------+
|  1792992 |
+----------+
1 row in set (2.26 sec)

原始字段varchar长度:

`main_order_id` varchar(20) NOT NULL COMMENT ‘主订单号‘,

字段varchar长度从20到85 不存在锁表:

 ALTER TABLE t_order_bill_detail_change_log  MODIFY COLUMN  `main_order_id` varchar(85) NOT NULL COMMENT ‘主订单号‘;

 root@node04 20:18:  [db_bill]>  ALTER TABLE t_order_bill_detail_change_log  MODIFY COLUMN  `main_order_id` varchar(85) NOT NULL COMMENT ‘主订单号‘;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

字段长度:

 `main_order_id` varchar(85) NOT NULL COMMENT ‘主订单号‘,

字段varchar 长度从85到86发生锁表:

发生锁表,耗时64秒:

 root@node04 20:26:  [db_bill]>  ALTER TABLE t_order_bill_detail_change_log  MODIFY COLUMN  `main_order_id` varchar(86) NOT NULL COMMENT ‘主订单号‘;
Query OK, 1792992 rows affected (1 min 4.07 sec)
Records: 1792992  Duplicates: 0  Warnings: 0

发生了锁表:
 root@node04 20:28:  [information_schema]>  select * from information_schema.INNODB_TRX\G
*************************** 1. row ***************************
                    trx_id: 2395935
                 trx_state: RUNNING
               trx_started: 2021-07-26 20:28:18
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 9961
       trx_mysql_thread_id: 4
                 trx_query: ALTER TABLE t_order_bill_detail_change_log  MODIFY COLUMN  `main_order_id` varchar(86) NOT NULL COMMENT ‘主订单号‘
       trx_operation_state: fetching rows
         trx_tables_in_use: 2
         trx_tables_locked: 3
          trx_lock_structs: 154
     trx_lock_memory_bytes: 24784
           trx_rows_locked: 9957
         trx_rows_modified: 9807
   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
1 row in set (0.00 sec)

字段长度大于86:

main_order_id varchar(86) NOT NULL COMMENT ‘主订单号‘,

修改 字段varchar 长度 从86到比86大的数值 也不会发生锁表的问题:

  ALTER TABLE t_order_bill_detail_change_log  MODIFY COLUMN  `main_order_id` varchar(172) NOT NULL COMMENT ‘主订单号‘;

  root@node04 21:00:  [db_bill]>  ALTER TABLE t_order_bill_detail_change_log  MODIFY COLUMN  `main_order_id` varchar(172) NOT NULL COMMENT ‘主订单号‘;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

字符集为utf8mb4 也是一样的。此处不再介绍了,感兴趣的话,可以测试下。

上一篇:[Vue]-03-vueRouter


下一篇:OpenFaaS实战之二:函数入门