MySQL锁:01.总览

  • 锁如何发生,如何解除。
  • 了解死锁的发生,和解决。
  • 为什么数据库要有锁?作用和影响是什么?没有锁会怎样?
  • MySQL里都有什么锁?
  • MyISAM锁
  • InnoDB锁
    • 锁类型
    • InnoDB锁实现
    • InnoDB锁案例
    • InnoDB死锁
    • InnoDB锁优化
  • 锁状态监控

MySQL锁:01.总览

锁总览

锁的作用

避免并发请求时对同一个数据对象同时修改,导致数据不一致。

加锁流程

  1. 事务T1在对某个数据对象R1操作之前,先向系统发出请求,对其加锁L1
  2. 之后,事务T1对该数据对象R1有了相应的控制,在T1释放L1之前,其它事务不能修改R1

锁对数据库的影响

锁等待

  • 锁L1锁定某个对象R1,锁L2等待该锁释放,如果不释放,会一直等待,或者达到系统预设的超时阈值后报错,整个事务回滚,或只回滚当前SQL。
  • 可以配置参数,行锁超时后事务会被回滚。
mysql> show global variables like '%rollback%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| innodb_rollback_on_timeout | OFF   |
| innodb_rollback_segments   | 128   |
+----------------------------+-------+
2 rows in set (0.00 sec)

死锁

  • 锁资源请求产生了回路,如:L1等待L2释放,L2等待L3释放,L3等待L1释放,死循环。

锁类型

  • 排他锁(X)
  • 共享锁(S)

锁范围

  • 全局锁(global lock)instance级别
  • 表级锁(table lock)
  • 行级锁(row lock)
  • 还有mutex,不属于锁,InnoDB内部保护机制,不可控,无法手动解锁,只能调整参数优化。

锁方式

  • 悲观锁
  • “不信任”其它事务,为了以防万一,总是先对数据对象加锁。
  • 事先不加锁,冲突检测过程中才加锁。(就是当前加锁后,并未真正锁,当另一个session尝试锁或其它行为时发生冲突检测,才察觉到加锁了。如同用书占座,只有当其他人想坐过来的时候,帮占座的人才会出面提出该座位已经被占用(被锁))

    select .. for update/for share 就是悲观锁。

  • 乐观锁
  • 不急着加锁,而是等到真的需要进行更新漏了,才再次查询并更新数据。
  • 提前加锁。MGR、PXC先在本节点加锁更新,再广播出去——如果其它节点加锁失败,那么本节点再回滚回去。
    • MGR、PXC用的就是乐观锁。

全局锁

全局读锁

  • global read lock 全局读锁
  • 一般是因为mysqldump、xtrabackup等备份请求发起
  • FTWRL,关闭instance下所有表,并加上全局读锁,防止被修改,直到提交unlock tables;
  • (实例中可能有不同的表引擎,在发起整个实例备份前,先将表关闭一下, 避免有其它会话正在修改表结构。关闭再打开并加全局读锁,防止表被DDL修改。)
  • 若用mysqldum之备份InnoDB无需记录binlog时,可以只加–single-transaction,不加–master-data选项。传送门:一致性备份:所有的表状态都在一个时间点。
  • xtrabackup时可以分开备份InnoDB和MyISAM。
  • 全局读锁时,任何innodb事务不能被提交。
  • 如果都是InnoDB表,可以无需锁表在线热备。
    MySQL锁:01.总览
    MySQL锁:01.总览

全局QC锁

QC已经永远说再见了。

  • 全局query cache锁(mutex)。最好关闭query cache
  • 对QC中的数据有更新时都会引发query cache lock,对应状态为: waiting for query cache lock
  • 关闭QC: query_cache_type=0 , query_cache_size=0

QC锁存在的问题:

  • 全局任何表数据的更新都会造成请求全局QC锁。
  • 当发起请求时,会将sql及结果放入qc,下次执行同样sql会从qc返回结果。
  • 但是两次执行之间如果发生数据修改,需要更新qc的时候,MySQL简单粗暴的处理方式:只要表数据更新,就会更新qc里关于这个表的所有的cache。所以只要表发生更新,就会请求全局qc这个排他锁,当实例有大量并发更新时,qc就会发生很严重的锁等待。

备份锁 backup lock

  • 8.0新增功能,为了保证备份一致性,需要backup_admin角色权限
  • 发起备份前,执行lock instance for backup,备份结束后执行unlock instance解锁
  • backup lock的作用时备份期间依旧允许DML操作,以及session级别的DDL操作,例如生成临时表。
    (但是建表、改表、删表、repair、truncate、optimize等都被禁止!)
  • 多个会话可以并行持有该锁。
  • 备份锁:降低全局读锁的影响。8.0开始所有数据都用innodb存储,发起备份锁便可以一致性备份。

A backup lock acquired by LOCK INSTANCE FOR BACKUP is independent of transactional locks and locks
taken by FLUSH TABLES tbl_name [, tbl_name] … WITH READ LOCK, and the following sequences of statements are permitted:
LOCK INSTANCE FOR BACKUP;
FLUSH TABLES tbl_name [, tbl_name] … WITH READ LOCK;
UNLOCK TABLES;
UNLOCK INSTANCE;
FLUSH TABLES tbl_name [, tbl_name] … WITH READ LOCK;
LOCK INSTANCE FOR BACKUP;
UNLOCK INSTANCE;
UNLOCK TABLES;

(但是建表、改表、删表、repair、truncate、optimize等都被禁止!)

mysql1> lock instance for backup;
Query OK, 0 rows affected (0.00 sec)

mysql3> select  * from metadata_locks;
+-------------+--------------------+----------------+-------------+-----------------------+-------------+---------------+-------------+-----------
| OBJECT_TYPE | OBJECT_SCHEMA      | OBJECT_NAME    | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE   | LOCK_DURATION | LOCK_STATUS | SOURCE
+-------------+--------------------+----------------+-------------+-----------------------+-------------+---------------+-------------+-----------
| BACKUP LOCK | NULL               | NULL           | NULL        |       139618985816432 | SHARED      | EXPLICIT      | GRANTED     | sql_backup
| TABLE       | performance_schema | metadata_locks | NULL        |       139619055733920 | SHARED_READ | TRANSACTION   | GRANTED     | sql_parse.

+-------------+--------------------+----------------+-------------+-----------------------+-------------+---------------+-------------+-----------
2 rows in set (0.00 sec)

mysql2> truncate table k0;
--hang

mysql3> select  * from metadata_locks;
+-------------+--------------------+----------------+-------------+-----------------------+---------------------+---------------+-------------+---
| OBJECT_TYPE | OBJECT_SCHEMA      | OBJECT_NAME    | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE           | LOCK_DURATION | LOCK_STATUS | SO
+-------------+--------------------+----------------+-------------+-----------------------+---------------------+---------------+-------------+---
| BACKUP LOCK | NULL               | NULL           | NULL        |       139618985816432 | SHARED              | EXPLICIT      | GRANTED     | sq
| SCHEMA      | kk                 | NULL           | NULL        |       139618851698880 | INTENTION_EXCLUSIVE | EXPLICIT      | GRANTED     | dd
| GLOBAL      | NULL               | NULL           | NULL        |       139618851437968 | INTENTION_EXCLUSIVE | STATEMENT     | GRANTED     | sq
| BACKUP LOCK | NULL               | NULL           | NULL        |       139618851457584 | INTENTION_EXCLUSIVE | TRANSACTION   | PENDING     | sq
| TABLE       | performance_schema | metadata_locks | NULL        |       139619055733920 | SHARED_READ         | TRANSACTION   | GRANTED     | sq
+-------------+--------------------+----------------+-------------+-----------------------+---------------------+---------------+-------------+---
5 rows in set (0.00 sec)

mysql1> lock instance for backup;
Query OK, 0 rows affected (0.00 sec)

mysql1> truncate table k0;    --- 但是session1 自己却能DDL
Query OK, 0 rows affected (0.84 sec)

作为对比,对比一下FTWRL时:当前session也会被阻塞

mysql1> flush table with read lock;
Query OK, 0 rows affected (0.01 sec)

mysql1> truncate table k0;
ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock

MDL锁

meta data lock

  • 5.5开始引入
  • 备份时防止对象被修改
  • tablesspace/schema、表、function/procedure/trigger/event等多种对象上加的锁
  • 事务开启后,会锁定表的meta data,其它会话对表有DDL操作时,均需等待MDL释放后方可继续。
  • 锁超时阈值定义参数:lock_wait_timeout,默认锁等待一年……强烈建议调低。避免加MDL锁忘记释放后导致超长阻塞。
  • 即便是只读查询、只读事务,也要尽快结束以释放MDL

MDL锁类型

INTENTION_EXCLUSIVE 意向排他锁,只用于范围上锁,例如lock table write. SHARED 共享锁,用于访问字典对象,而不访问数据,例如 create table a like b SHARED_HIGH_PRIO 只访问字典对象,例如 desc table_a SHARED_READ 共享读锁,用于读取数据,如事务中的select rows SHARED_WRITE 共享写锁,用于修改数据,如事务中的update rows SHARED_NO_WRITE 共享非写锁,允许读取数据,阻塞其它TX修改数据,用在ALTER TABLE第一阶段 SHARED_NO_READ_WRITE 用于访问字典,读写数据,阻塞其它TX读写数据,例如lock table write SHARED_READ_ONLY 只读锁,常见于lock table x read EXCLUSIVE 排他锁,可以修改字典和数据,例如alter table

MDL锁的兼容性

IX S SH SR SW SNW SNRW X IX √ √ √ √ √ √ √ √ S √ √ √ √ √ √ √ × SH √ √ √ √ √ √ √ × SR √ √ √ √ √ √ × × SW √ √ √ √ √ × × × SNW √ √ √ √ × × × × SNRW √ √ √ × × × × × X √ × × × × × × ×

确认MDL锁源头以及消除方法

上锁后便可以在performance_schema.metadata_locks 查询到。
上锁后发生锁等待时,可以在sys.schema_table_lock_waits 查询。
有没有锁,和有没有锁等待是两个不同的概念。

  • 启用MDL的P_S统计
  • p_s.setup_consumers.global_instrumentation
  • p_s.setup_instruments.wait/lock/metadata/sql/mdl 打开可以动态打开,立即生效。
    但是关闭的话,只有新的session才能有效果(等待亲测)
  • 查询MDL锁状态信息:
  • show proesslist;
  • select * from performance_schema.metadata_locks\G
  • 通过metadata_locks查看MDL锁事件
mysql1> select * from performance_schema.metadata_locks where object_schema != 'performance_schema'\G
Empty set (0.00 sec)

mysql2> select *,sleep(1000) from k1 limit 2;

mysql1> select * from performance_schema.metadata_locks where object_schema != 'performance_schema'\G
*************************** 1. row ***************************
          OBJECT_TYPE: TABLE
        OBJECT_SCHEMA: kk
          OBJECT_NAME: k1
          COLUMN_NAME: NULL
OBJECT_INSTANCE_BEGIN: 139618985616624   #是μs
            LOCK_TYPE: SHARED_READ
        LOCK_DURATION: TRANSACTION
          LOCK_STATUS: GRANTED
               SOURCE: sql_parse.cc:6052
      OWNER_THREAD_ID: 52
       OWNER_EVENT_ID: 54
1 row in set (0.00 sec)

mysql3> select *,sleep(100) from k1 limit 2;

mysql1> select * from performance_schema.metadata_locks where object_schema != 'performance_schema'\G
*************************** 1. row ***************************
          OBJECT_TYPE: TABLE
        OBJECT_SCHEMA: kk
          OBJECT_NAME: k1
          COLUMN_NAME: NULL
OBJECT_INSTANCE_BEGIN: 139618985616624
            LOCK_TYPE: SHARED_READ
        LOCK_DURATION: TRANSACTION
          LOCK_STATUS: GRANTED
               SOURCE: sql_parse.cc:6052
      OWNER_THREAD_ID: 52
       OWNER_EVENT_ID: 56
*************************** 2. row ***************************
          OBJECT_TYPE: TABLE
        OBJECT_SCHEMA: kk
          OBJECT_NAME: k1
          COLUMN_NAME: NULL
OBJECT_INSTANCE_BEGIN: 139619052075760
            LOCK_TYPE: SHARED_READ
        LOCK_DURATION: TRANSACTION
          LOCK_STATUS: GRANTED
               SOURCE: sql_parse.cc:6052
      OWNER_THREAD_ID: 53
       OWNER_EVENT_ID: 13
  • 如何拿着metadata lock视图查到的thread_id 找到对应的process?
mysql1> show processlist;
+----+-----------------+-----------+------+---------+--------+------------------------+--------------------------------------+
| Id | User            | Host      | db   | Command | Time   | State                  | Info                                 |
+----+-----------------+-----------+------+---------+--------+------------------------+--------------------------------------+
|  4 | event_scheduler | localhost | NULL | Daemon  | 260212 | Waiting on empty queue | NULL                                 |
| 12 | root            | localhost | NULL | Query   |      0 | starting               | show processlist                     |
| 13 | root            | localhost | kk   | Query   |     37 | User sleep             | select *,sleep(1000) from k1 limit 2 |
| 14 | root            | localhost | kk   | Query   |     27 | User sleep             | select *,sleep(100) from k1 limit 2  |
+----+-----------------+-----------+------+---------+--------+------------------------+--------------------------------------+
4 rows in set (0.00 sec)

mysql1> select * from performance_schema.threads where PROCESSLIST_ID in (13,14);
+-----------+---------------------------+------------+----------------+------------------+------------------+----------------+---------------------+------------------+-------------------+--------------------------------------+------------------+------+--------------+---------+-----------------+--------------+----------------+
| THREAD_ID | NAME                      | TYPE       | PROCESSLIST_ID | PROCESSLIST_USER | PROCESSLIST_HOST | PROCESSLIST_DB | PROCESSLIST_COMMAND | PROCESSLIST_TIME | PROCESSLIST_STATE | PROCESSLIST_INFO                     | PARENT_THREAD_ID | ROLE | INSTRUMENTED | HISTORY | CONNECTION_TYPE | THREAD_OS_ID | RESOURCE_GROUP |
+-----------+---------------------------+------------+----------------+------------------+------------------+----------------+---------------------+------------------+-------------------+--------------------------------------+------------------+------+--------------+---------+-----------------+--------------+----------------+
|        52 | thread/sql/one_connection | FOREGROUND |             13 | root             | localhost        | kk             | Query               |              149 | User sleep        | select *,sleep(1000) from k1 limit 2 |             NULL | NULL | YES          | YES     | Socket          |          691 | USR_default    |
|        53 | thread/sql/one_connection | FOREGROUND |             14 | root             | localhost        | kk             | Query               |              139 | User sleep        | select *,sleep(100) from k1 limit 2  |             NULL | NULL | YES          | YES     | Socket          |          693 | USR_default    |
+-----------+---------------------------+------------+----------------+------------------+------------------+----------------+---------------------+------------------+-------------------+--------------------------------------+------------------+------+--------------+---------+-----------------+--------------+----------------+

mysql2> begin ;
Query OK, 0 rows affected (0.00 sec)

mysql2> update k1 set id=22 where id=2;
Query OK, 1793 rows affected (0.01 sec)
Rows matched: 1793  Changed: 1793  Warnings: 0

mysql3> begin;
Query OK, 0 rows affected (0.00 sec)

mysql3> update k1 set id=22 where id=2;

mysql> select * from performance_schema.metadata_locks where object_schema != 'performance_schema'\G
*************************** 1. row ***************************
          OBJECT_TYPE: TABLE
        OBJECT_SCHEMA: kk
          OBJECT_NAME: k1
          COLUMN_NAME: NULL
OBJECT_INSTANCE_BEGIN: 139618985616624
            LOCK_TYPE: SHARED_WRITE
        LOCK_DURATION: TRANSACTION
          LOCK_STATUS: GRANTED    #拿到了MDL锁
               SOURCE: sql_parse.cc:6052
      OWNER_THREAD_ID: 52
       OWNER_EVENT_ID: 66
*************************** 2. row ***************************
          OBJECT_TYPE: TABLE
        OBJECT_SCHEMA: kk
          OBJECT_NAME: k1
          COLUMN_NAME: NULL
OBJECT_INSTANCE_BEGIN: 139619052075760
            LOCK_TYPE: SHARED_WRITE
        LOCK_DURATION: TRANSACTION
          LOCK_STATUS: GRANTED    #拿到了MDL锁
               SOURCE: sql_parse.cc:6052
      OWNER_THREAD_ID: 53
       OWNER_EVENT_ID: 19
2 rows in set (0.00 sec)

mysql> show processlist;
+----+-----------------+-----------+------+---------+--------+------------------------+--------------------------------+
| Id | User            | Host      | db   | Command | Time   | State                  | Info                           |
+----+-----------------+-----------+------+---------+--------+------------------------+--------------------------------+
|  4 | event_scheduler | localhost | NULL | Daemon  | 261969 | Waiting on empty queue | NULL                           |
| 12 | root            | localhost | NULL | Query   |      0 | starting               | show processlist               |
| 13 | root            | localhost | kk   | Sleep   |    277 |                        | NULL                           |
| 14 | root            | localhost | kk   | Query   |     14 | updating               | update k1 set id=22 where id=2 |
+----+-----------------+-----------+------+---------+--------+------------------------+--------------------------------+
4 rows in set (0.00 sec)

mysql> select * from sys.schema_table_lock_waits;
Empty set (0.01 sec)

  • 为什么都拿到了MDL锁?
    通过前面的MDL锁兼容性表格可知,SW和SW可以兼容并存的。
    理解一下可以得知:行锁虽然被阻塞,但是更新所需的MDL锁是拿到的——允许同时加(获取)shared_write锁, 只不过在等待行锁而已。

只有对表进行表级别锁时,才会互斥

  • 表级别锁阻塞实验
mysql2> lock table k1 read;
Query OK, 0 rows affected (2 min 37.02 sec)

mysql1> select * from performance_schema.metadata_locks where object_schema != 'performance_schema'\
*************************** 1. row ***************************
          OBJECT_TYPE: TABLE
        OBJECT_SCHEMA: kk
          OBJECT_NAME: k1
          COLUMN_NAME: NULL
OBJECT_INSTANCE_BEGIN: 139618985329072
            LOCK_TYPE: SHARED_READ_ONLY
        LOCK_DURATION: TRANSACTION
          LOCK_STATUS: GRANTED
               SOURCE: sql_parse.cc:6052
      OWNER_THREAD_ID: 52
       OWNER_EVENT_ID: 69
1 row in set (0.00 sec)

mysql3> begin;
Query OK, 0 rows affected (0.00 sec)

mysql3> update k1 set id=22 where id=2;
--hang住了。

mysql1> mysql> select * from performance_schema.metadata_locks where object_schema != 'performance_sGhema'\
*************************** 1. row ***************************
          OBJECT_TYPE: TABLE
        OBJECT_SCHEMA: kk
          OBJECT_NAME: k1
          COLUMN_NAME: NULL
OBJECT_INSTANCE_BEGIN: 139618985329072
            LOCK_TYPE: SHARED_READ_ONLY
        LOCK_DURATION: TRANSACTION
          LOCK_STATUS: GRANTED
               SOURCE: sql_parse.cc:6052
      OWNER_THREAD_ID: 52
       OWNER_EVENT_ID: 69
*************************** 2. row ***************************
          OBJECT_TYPE: TABLE
        OBJECT_SCHEMA: kk
          OBJECT_NAME: k1
          COLUMN_NAME: NULL
OBJECT_INSTANCE_BEGIN: 139619052222560
            LOCK_TYPE: SHARED_WRITE
        LOCK_DURATION: TRANSACTION
          LOCK_STATUS: PENDING # 加SW锁被阻塞
               SOURCE: sql_parse.cc:6052
      OWNER_THREAD_ID: 53
       OWNER_EVENT_ID: 28
2 rows in set (0.00 sec)

  • 查询锁等待信息,利用sys schema查询MDL等待信息
mysql> select * from sys.schema_table_lock_waits\G
*************************** 1. row ***************************
               object_schema: kk
                 object_name: k1
           waiting_thread_id: 53
                 waiting_pid: 14
             waiting_account: root@localhost
           waiting_lock_type: SHARED_WRITE
       waiting_lock_duration: TRANSACTION
               waiting_query: update k1 set id=22 where id=2
          waiting_query_secs: 56
 waiting_query_rows_affected: 0
 waiting_query_rows_examined: 0
          blocking_thread_id: 52
                blocking_pid: 13
            blocking_account: root@localhost
          blocking_lock_type: SHARED_READ_ONLY
      blocking_lock_duration: TRANSACTION
     sql_kill_blocking_query: KILL QUERY 13
sql_kill_blocking_connection: KILL 13
1 row in set (0.00 sec)

mysql> show processlist;
+----+-----------------+-----------+------+---------+--------+---------------------------------+--------------------------------+
| Id | User            | Host      | db   | Command | Time   | State                           | Info                           |
+----+-----------------+-----------+------+---------+--------+---------------------------------+--------------------------------+
|  4 | event_scheduler | localhost | NULL | Daemon  | 263713 | Waiting on empty queue          | NULL                           |
| 12 | root            | localhost | NULL | Query   |      0 | starting                        | show processlist               |
| 13 | root            | localhost | kk   | Sleep   |    434 |                                 | NULL                           |
| 14 | root            | localhost | kk   | Query   |    218 | Waiting for table metadata lock | update k1 set id=22 where id=2 |
+----+-----------------+-----------+------+---------+--------+---------------------------------+--------------------------------+
4 rows in set (0.00 sec)


* 由此可知,shared_write和shared_read_only互斥。
* 由查询结果可知,thread 52 阻塞了thread 53的请求,并且给出了处理办法:
– kill query 只能将id里当前在跑的sql中止在这个实验里, kill query 是没用的——show processlist看到,pid 13当前没有语句进行。
– 只有 kill 13才有效。
– 当然了, 也可以在13中结束事务,释放锁:

mysql2> unlock tables;
Query OK, 0 rows affected (0.00 sec)

mysql3> update k1 set id=22 where id=2;
Query OK, 0 rows affected (5 min 40.74 sec)
Rows matched: 0  Changed: 0 Warnings: 0

表锁

表锁一般在server层面实现。
InnoDB表还有IS/IX表级锁,以及auto-inc锁。

读锁

lock table t1 read;

  • 持有读锁的会话可以读表,但是不能写表。
  • 允许多个会话同时持有读锁

写锁

lock table t1 write

  • 持有写锁的会话既可以读表,也可以写表
  • 只有持有写锁的会话才可以读写该表
  • 其它会话访问该表或者请求加锁都会被阻塞,直到锁释放。

加锁

  • lock table t1 read;
  • 多个session都可以对一个表加读锁
  • lock table t1 write
  • 也许需要先解除之前上的读锁。(自己试一下)
  • 写锁是X锁,同一时间一个表只能被一个session加写锁。

释放锁

MySQL解除表级锁目前是解除全部表级锁,无法单独解除某个锁。(help get_lock 好像可以,自己研究一下。)

  • unlock tables;
  • 断开连接或者被kill
  • 【错误,需要验证版本】执行lock table
  • 【错误,需要验证版本】显示开启一个事务

MyISAM锁

  • 默认是表锁,读写互斥,仅只读共享
  • 读锁,lock table xxx read,自身只读,不能写。其它线程仍可读,不能写。多个线程都可提交read lock
  • 写锁,lock table xxx write,自身可读写,其它线程完全不可读写。
  • 写锁优先级高于读锁
  • select自动加读锁(共享锁)
  • 其它DML、DDL自动加写锁(排他锁)
  • 释放锁见上文。

放弃MyISAM吧,都是表锁。

MySQL锁:01.总览

Original: https://www.cnblogs.com/konggg/p/14133916.html
Author: 孔个个
Title: MySQL锁:01.总览

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/621092/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Linux 常用命令

    Linux 常用命令 free -h:查看服务器下内存 df -lh:查看磁盘空间 du -sh *:查看文件夹下文件占用多少空间 uname -a:查看系统版本 which ja…

    数据库 2023年6月6日
    075
  • JavaWeb核心篇(7)——VUE和Element

    VUE&Element 今日目标: 能够使用VUE中常用指令和插值表达式 能够使用VUE生命周期函数 mounted 能够进行简单的 Element 页面修改 能够完成查询…

    数据库 2023年6月14日
    077
  • entitybuilder–一个简单的业务通用框架

    关于业务通用框架的思考 业务系统是千差万别的,例如,保存、更新和删除订单,或者保存订单和保存客户,走的根本不是一个流程。但是,它们还是有共同点,它们的流程大致可以分成下面的几个部分…

    数据库 2023年6月6日
    083
  • python中组合数据的操作

    2022-09-26 组合数据类型: 拷贝: deep(深拷贝) shallow(浅拷贝) 区别:例如,文件中有一个指针指向另一块存储空间,如果是深拷贝则将指向的那一块文件内容也全…

    数据库 2023年6月14日
    080
  • SQL Archery 代码说明及优化(一)

    1.字段加密–django-mirage-field 一个django模型字段,在保存到数据库时对数据进行加密,在从数据库获取数据时进行解密。它使数据库中的数据始终加密…

    数据库 2023年6月16日
    092
  • 一篇文章带你掌握主流数据库框架——MyBatis

    一篇文章带你掌握主流数据库框架——MyBatis MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。 在之前的文章中我们学习了MYSQL和JDBC…

    数据库 2023年6月14日
    085
  • 系统发布springboot项目

    首先把项目终止服务,但这样的做法不是很好,也可以来个配置文件 1.查看运行的java文件有哪些,位置在哪里,端口号是多少 ps -ef | grep java 2.结束端口进程的运…

    数据库 2023年6月6日
    075
  • DELL误删raid后恢复方法

    DELL误删raid后恢复方法 一台有RAID1信息的硬盘A,一块误删的硬盘B 1.插入硬盘A和B,启动,再按Ctrl+R键,进入raid管理 发现没有硬盘信息,按F2键 选择Fo…

    数据库 2023年6月9日
    085
  • Java学习-第一部分-第一阶段-第七节:面向对象编程(中级)

    面向对象编程(中级) 笔记目录:(https://www.cnblogs.com/wenjie2000/p/16378441.html) lntelliJ IDEA ●IDEA介绍…

    数据库 2023年6月11日
    089
  • [springmvc]springmvc的实现流程原理,以及快速创建一个三层架构项目

    1.回顾mvc 模型 模型(dao,service):业务逻辑,保存数据的状态 视图 视图(jsp,html……):展示页面 控制器 控制(servlet)…

    数据库 2023年6月16日
    063
  • day43-反射02

    Java反射02 2.Class类 2.1基本介绍 Class类也是类,因此也继承Object类 Class类对象不是new出来的,而是系统创建的 对于某个类的Class类对象,在…

    数据库 2023年6月11日
    073
  • Win10系统-接口自动化测试持续集成

    使用工具:jdk+jmeter+Ant+jenkins jdk-1.8.0_241版本【安装参考链接:https://blog.51cto.com/u_15463439/52268…

    数据库 2023年6月14日
    088
  • Java8日期时间(LocalDate、LocalTime、LocalDateTime)

    在看题的时候发现了Java8中新加入的日期时间类,觉得这个小哥写的不错,自己也跟着练习下。原文地址:https://blog.csdn.net/yy139926/article/d…

    数据库 2023年6月14日
    074
  • 文件输入/输出流

    文件输入/输出流程序 运行期间,大部分数据都被存储在 内存中,当程序结束或被关闭时,存储在内存中的数据将会 消失。如果要 永久保存数据,那么最好的办法就是把数据保存到 磁盘的文件中…

    数据库 2023年6月16日
    0107
  • 深入汇编指令理解Java关键字volatile

    volatile是什么 volatile关键字是Java提供的一种轻量级同步机制。它能够保证可见性和有序性,但是不能保证原子性 可见性 对于volatile的可见性,先看看这段代码…

    数据库 2023年6月16日
    073
  • == 和 equals 的区别

    1. == 概念:==是一个比较运算符 == 既可以判断基本类型,又可以判断引用类型 ==判断基本类型时,判断的是值是否相等。示例:int i = 10; ==判断引用类型时,判断…

    数据库 2023年6月11日
    075
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球