我的编程空间,编程开发者的网络收藏夹
学习永远不晚

MYSQL中一个特殊的MDL LOCK死锁的示例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

MYSQL中一个特殊的MDL LOCK死锁的示例分析

本篇文章为大家展示了MYSQL中一个特殊的MDL LOCK死锁的示例分析,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

一、问题由来
前段开发反馈时间线上数据库老是出现死锁情况,而我们设置了innodb_print_all_deadlocks,但是在
相应的时间点没有找到任何相应的死锁的信息,从而导致我们获得任何有用的信息,也不能定位问题的
原因。

二、问题思考和分析
后来开发将出错码发给我,我看到这个错误码确实是MYSQL报出来的如下:
{ "ER_LOCK_DEADLOCK", 1213, "Deadlock found when trying to get lock; try restarting transaction" },
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
那么能够肯定一点这个死锁是MYSQL报出来的。那么为什么innodb没有任何表示呢?难道是什么BUG
继而在
https://bugs.mysql.com/
找了一下BUGS也没有找,后来我思考这个问题,既然是死锁就会是相应的死锁检测算法抛出来,我们知道MYSQL
上层还有MDL LOCK,并不是只有innodb相应的lock才会有进行死锁检测,会不是因为MDL LOCK死锁照成的呢?
我在MDL.CC中找到了如下代码其实也是我上文说的MDL_context::acquire_lock 函数,上文说过这个函数是
根据MDL_REQUEST尝试获得MDL LOCK的主要函数。

点击(此处)折叠或打开

  1. switch (wait_status)

  2.     {

  3.     case MDL_wait::VICTIM:

  4.       my_error(ER_LOCK_DEADLOCK, MYF(0));

  5.       break;

  6.     case MDL_wait::TIMEOUT:

  7.       my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));

  8.       break;

  9.     case MDL_wait::KILLED:

  10.       if (get_owner()->is_killed() == ER_QUERY_TIMEOUT)

  11.         my_error(ER_QUERY_TIMEOUT, MYF(0));

  12.       else

  13.         my_error(ER_QUERY_INTERRUPTED, MYF(0));

  14.       break;

  15.     default:

  16.       DBUG_ASSERT(0);

  17.       break;

  18.     }

注意红色部分,其实这里死锁问题基本确定不是innodb层触发的,既然不是innodb下层触发,innodb当然不会打印
出任何信息。为什么innodb层不打印死锁信息的原因找到了,但是什么情况下会出现MDL LOCK的死锁呢?

三、问题定位

既然要产生死锁必须满足一些条件:
1、至少2个独立的线程(会话)。
2、单位操作中包含多个相对独立的加锁步骤,有一定的时间差
   比如一个事物里面的多个操作
   还比如repeat操作(虽然非常段也是有的)。 关于replace的死锁问题参考我的文章如下:
    http://blog.itpub.net/7728585/viewspace-2141409/   

3、多个线程(会话)之间加锁对象必须有相互等待的情况发生,并且等待出现环状。

顺便提一句,死锁一般处理方式有3种
A、事前预测
B、资源分级
C、事后检测释放
而MDL LOCK和INNODB都使用了C时候检测释放,其算法应该是利用图的(DSF or BSF)遍历进行判定,这一块以后要好好看一下。

那么我考虑到使用MYSQLDUMP进行的备份的时候可能出现一些MDL LOCK的情况,比如加上-F, --flush-logs  --single-transaction会
短暂的使用 flush table with read lock;
如下:

2017-08-08T06:22:44.916055Z   15 Connect        root@localhost on  using Socket
2017-08-08T06:22:44.916270Z   15 Query  
2017-08-08T06:22:44.916521Z   15 Query  
2017-08-08T06:22:44.916604Z   15 Query  FLUSH TABLES
2017-08-08T06:22:44.922889Z   15 Query  FLUSH TABLES WITH READ LOCK
2017-08-08T06:22:44.923009Z   15 Refresh
/mysqldata/mysql5.7/bin/mysqld, Version: 5.7.13-log (Source distribution). started with:
Tcp port: 3307  Unix socket: /mysqldata/mysql5.7/mysqld3307.sock
Time                 Id Command    Argument
2017-08-08T06:22:44.949003Z   15 Query  SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
2017-08-08T06:22:44.949089Z   15 Query  START TRANSACTION
2017-08-08T06:22:44.949200Z   15 Query  SHOW VARIABLES LIKE 'gtid\_mode'
2017-08-08T06:22:44.953060Z   15 Query  SELECT @@GLOBAL.GTID_EXECUTED
2017-08-08T06:22:44.953160Z   15 Query  UNLOCK TABLES

如前文所述这个操作会在GLOBAL上加一把S锁
2017-08-03T18:19:11.603971Z 3 [Note] (--->MDL PRINT) Namespace is:GLOBAL 
2017-08-03T18:19:11.603994Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED(S) 

而导致所有的需要在GLOBAL上加IX锁的操作全部等待比如(DML操作/DDL操作),但是这里的flush table with read lock
并不符合上面描述的死锁产生的条件,不管如何先检查一下是不是MYSQLDUMP的问题,这一检查真的检查到了问题,我们
MYSQL备份的时候,进行了一次单独的表结构的备份,同事认为很快而没有加--single-transaction,然后检查备份结束的
时间,基本和死锁出现的时间点一致,那么问题转为如果不加--single-transaction,MYSQLDUMP如何加锁。

实际上这个时候从general日志来看,加锁如下:
2017-08-08T06:33:22.427691Z   20 Init DB        dumptest
2017-08-08T06:33:22.427794Z   20 Query  SHOW CREATE DATABASE IF NOT EXISTS `dumptest`
2017-08-08T06:33:22.428100Z   20 Query  show tables
2017-08-08T06:33:22.428443Z   20 Query  LOCK TABLES `kkkk` READ ,`llll` READ
2017-08-08T06:33:22.428551Z   20 Query  show table status like 'kkkk'
2017-08-08T06:33:22.428870Z   20 Query  SET SQL_QUOTE_SHOW_CREATE=1
2017-08-08T06:33:22.428929Z   20 Query  SET SESSION character_set_results = 'binary'
2017-08-08T06:33:22.429026Z   20 Query  show create table `kkkk`
2017-08-08T06:33:22.429157Z   20 Query  SET SESSION character_set_results = 'utf8'
2017-08-08T06:33:22.429212Z   20 Query  show fields from `kkkk`
2017-08-08T06:33:22.429534Z   20 Query  SELECT * FROM `kkkk`
2017-08-08T06:33:22.429680Z   20 Query  SET SESSION character_set_results = 'binary'
2017-08-08T06:33:22.429721Z   20 Query  use `dumptest`
2017-08-08T06:33:22.429769Z   20 Query  select @@collation_database
2017-08-08T06:33:22.429830Z   20 Query  SHOW TRIGGERS LIKE 'kkkk'
2017-08-08T06:33:22.430141Z   20 Query  SET SESSION character_set_results = 'utf8'
2017-08-08T06:33:22.430195Z   20 Query  show table status like 'llll'
2017-08-08T06:33:22.430411Z   20 Query  SET SQL_QUOTE_SHOW_CREATE=1
2017-08-08T06:33:22.430456Z   20 Query  SET SESSION character_set_results = 'binary'
2017-08-08T06:33:22.430493Z   20 Query  show create table `llll`
2017-08-08T06:33:22.430557Z   20 Query  SET SESSION character_set_results = 'utf8'
2017-08-08T06:33:22.430599Z   20 Query  show fields from `llll`
2017-08-08T06:33:22.430813Z   20 Query  SELECT * FROM `llll`
2017-08-08T06:33:22.430909Z   20 Query  SET SESSION character_set_results = 'binary'
2017-08-08T06:33:22.430945Z   20 Query  use `dumptest`
2017-08-08T06:33:22.431003Z   20 Query  select @@collation_database
2017-08-08T06:33:22.431098Z   20 Query  SHOW TRIGGERS LIKE 'llll'
2017-08-08T06:33:22.431330Z   20 Query  SET SESSION character_set_results = 'utf8'
2017-08-08T06:33:22.431375Z   20 Query  UNLOCK TABLES

我的dumptest数据只有两个表kkkk和llll,我们可以看到mysqldump通过LOCK TABLES `kkkk` READ ,`llll` READ 进行加锁,
备份完成后使用unlock tables解锁。其实这就是问题的根本原因。它会照成MDL死锁的产生。如果加上--single-transaction 则不会,
会使用SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ改变隔离级别为RR使用事物来保证数据的一致,
而不是LOCK TABLES来保证数据的一致性。

四、模拟MDL死锁和兼容性分析
首先我们需要看一下 LOCK TABLES a READ ,b READ 到底加了哪些MDL LOCK,这个通过我在MDL.CC中加入的打印函数my_print_ticket可以看到(具体在上文)
如下:
LOCK TABLES a READ ,b READ ;

2017-08-08T07:12:11.764164Z 2 [Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-08T07:12:11.764184Z 2 [Note] (>MDL PRINT) Thread id is 2: 
2017-08-08T07:12:11.764201Z 2 [Note] (->MDL PRINT) DB_name is:test 
2017-08-08T07:12:11.764258Z 2 [Note] (-->MDL PRINT) OBJ_name is:a 
2017-08-08T07:12:11.764344Z 2 [Note] (--->MDL PRINT) Namespace is:TABLE 
2017-08-08T07:12:11.764363Z 2 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_READ_ONLY(SRO) 
2017-08-08T07:12:11.764376Z 2 [Note] (------>MDL PRINT) Mdl  duration is:MDL_TRANSACTION 


2017-08-08T07:12:11.764586Z 2 [Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-08T07:12:11.764605Z 2 [Note] (>MDL PRINT) Thread id is 2: 
2017-08-08T07:12:11.764620Z 2 [Note] (->MDL PRINT) DB_name is:test 
2017-08-08T07:12:11.764634Z 2 [Note] (-->MDL PRINT) OBJ_name is:b 
2017-08-08T07:12:11.764648Z 2 [Note] (--->MDL PRINT) Namespace is:TABLE 
2017-08-08T07:12:11.764687Z 2 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_READ_ONLY(SRO) 
2017-08-08T07:12:11.764704Z 2 [Note] (------>MDL PRINT) Mdl  duration is:MDL_TRANSACTION 

我们可以清楚的看到本语句会对a和b分别调用函数MDL_context::acquire_lock进行加锁为object的SRO MDL锁类型,虽然是一个语句但是加锁却是分开的,
对于SRO锁兼容性如下
       Request  |  Granted requests for lock                  |
        type    | S  SH  SR  SW  SWLP  SU  SRO  SNW  SNRW  X  |
      ----------+---------------------------------------------+
      SRO       | +   +   +   -    -    +   +    +    -    -  |

可以看到SRO和SW\SNRW\X均不兼容,也就是和DML(SW)\SNRW(LOCK TABLE WRITE)\X(DDL) 不兼容。

如果有另外一个事物需要对a和b进行DML操作,那么MDL 死锁出现了如下:

THREAD1                                                   THREAD2
begin;(事物开始)
insert into b values(1);

                                                                 LOCK TABLES a READ ,b READ ; (堵塞)

insert into a values(1);(堵塞死锁)


现在我们来分析一下
线程1
begin;(事物开始)
insert into b values(1); 
获得MDL LOCK 如下:
2017-08-08T07:25:45.875676Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-08T07:25:45.875699Z 3 [Note] (>MDL PRINT) Thread id is 3: 
2017-08-08T07:25:45.875713Z 3 [Note] (--->MDL PRINT) Namespace is:GLOBAL 
2017-08-08T07:25:45.875726Z 3 [Note] (---->MDL PRINT) Fast path is:(Y)
2017-08-08T07:25:45.875740Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_INTENTION_EXCLUSIVE(IX) 
2017-08-08T07:25:45.875757Z 3 [Note] (------>MDL PRINT) Mdl  duration is:MDL_STATEMENT 
2017-08-08T07:25:45.875772Z 3 [Note] (------->MDL PRINT) Mdl  status is:GRANTED 
2017-08-08T07:25:45.875798Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-08T07:25:45.875812Z 3 [Note] (>MDL PRINT) Thread id is 3: 
2017-08-08T07:25:45.875826Z 3 [Note] (->MDL PRINT) DB_name is:test 
2017-08-08T07:25:45.875839Z 3 [Note] (-->MDL PRINT) OBJ_name is:b 
2017-08-08T07:25:45.875853Z 3 [Note] (--->MDL PRINT) Namespace is:TABLE 
2017-08-08T07:25:45.875875Z 3 [Note] (---->MDL PRINT) Fast path is:(Y)
2017-08-08T07:25:45.875888Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_WRITE(SW) 
2017-08-08T07:25:45.875900Z 3 [Note] (------>MDL PRINT) Mdl  duration is:MDL_TRANSACTION 
2017-08-08T07:25:45.875913Z 3 [Note] (------->MDL PRINT) Mdl  status is:GRANTED 

GLOBAL先不考虑,可以看到会在b表上获得SW的object mdl lock.

线程2

LOCK TABLES a READ ,b READ ; (堵塞)

2017-08-08T07:27:28.684508Z 2 [Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-08T07:27:28.684534Z 2 [Note] (>MDL PRINT) Thread id is 2: 
2017-08-08T07:27:28.684546Z 2 [Note] (->MDL PRINT) DB_name is:test 
2017-08-08T07:27:28.684558Z 2 [Note] (-->MDL PRINT) OBJ_name is:a 
2017-08-08T07:27:28.684569Z 2 [Note] (--->MDL PRINT) Namespace is:TABLE 
2017-08-08T07:27:28.684580Z 2 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_READ_ONLY(SRO) 
2017-08-08T07:27:28.684592Z 2 [Note] (------>MDL PRINT) Mdl  duration is:MDL_TRANSACTION 
2017-08-08T07:27:28.684604Z 2 [Note] (------->MDL PRINT) Mdl  status is:GRANTED 

2017-08-08T07:27:28.684622Z 2 [Note] (acquire_lock)THIS MDL LOCK acquire WAIT(MDL_LOCK WAIT QUE)!
2017-08-08T07:27:28.684633Z 2 [Note] (>MDL PRINT) Thread id is 2: 
2017-08-08T07:27:28.684644Z 2 [Note] (->MDL PRINT) DB_name is:test 
2017-08-08T07:27:28.684824Z 2 [Note] (-->MDL PRINT) OBJ_name is:b 
2017-08-08T07:27:28.684838Z 2 [Note] (--->MDL PRINT) Namespace is:TABLE 
2017-08-08T07:27:28.684850Z 2 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_READ_ONLY(SRO) 
2017-08-08T07:27:28.684871Z 2 [Note] (------>MDL PRINT) Mdl  duration is:MDL_TRANSACTION 
2017-08-08T07:27:28.684884Z 2 [Note] (------->MDL PRINT) Mdl  status is:EMPTY 

我们可以清楚的看到a表上的SRO获得成功,但是b表上的MDL LOCK 需求则进入了MDL_LOCK WAIT QUE等待了
及由于b表已经被线程1的insert语句拿到了SW锁,线程2想要获得b表的SRO锁需要等待
Waiting for table metadata lock | lock table a read,b read 

线程1

再次执行
mysql> insert into a values(1);
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

2017-08-08T07:31:13.053322Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-08T07:31:13.053359Z 3 [Note] (>MDL PRINT) Thread id is 3: 
2017-08-08T07:31:13.053388Z 3 [Note] (--->MDL PRINT) Namespace is:GLOBAL 
2017-08-08T07:31:13.053401Z 3 [Note] (---->MDL PRINT) Fast path is:(Y)
2017-08-08T07:31:13.053417Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_INTENTION_EXCLUSIVE(IX) 
2017-08-08T07:31:13.053589Z 3 [Note] (------>MDL PRINT) Mdl  duration is:MDL_STATEMENT 
2017-08-08T07:31:13.053613Z 3 [Note] (------->MDL PRINT) Mdl  status is:GRANTED 
2017-08-08T07:31:13.053658Z 3 [Note] (acquire_lock)THIS MDL LOCK acquire WAIT(MDL_LOCK WAIT QUE)!
2017-08-08T07:31:13.053676Z 3 [Note] (>MDL PRINT) Thread id is 3: 
2017-08-08T07:31:13.053694Z 3 [Note] (->MDL PRINT) DB_name is:test 
2017-08-08T07:31:13.053711Z 3 [Note] (-->MDL PRINT) OBJ_name is:a 
2017-08-08T07:31:13.053728Z 3 [Note] (--->MDL PRINT) Namespace is:TABLE 
2017-08-08T07:31:13.054065Z 3 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_WRITE(SW) 
2017-08-08T07:31:13.054092Z 3 [Note] (------>MDL PRINT) Mdl  duration is:MDL_TRANSACTION 
2017-08-08T07:31:13.054118Z 3 [Note] (-------->MDL PRINT) Mdl  status is:VICTIM

我们这里线程1想要获得a表的sw mdl lock,但是线程2持有a表的SRO mdl lock,显然他们不兼容,死锁出现(VICTIM)
MDL死锁出现后根据一个权重来进行回滚如下:
  static const uint DEADLOCK_WEIGHT_DML= 0;
  static const uint DEADLOCK_WEIGHT_ULL= 50;
  static const uint DEADLOCK_WEIGHT_DDL= 100;
虽然没有研究死锁检测的原理,但是这里应该是带权重的一个图,回滚权重小的操作。最后线程1的事物操作被回滚了。
从打印来看事物回滚后,LOCK TABLES a READ ,b READ ;获得了全部的SRO MDL LOCK成功了,打印如下:

2017-08-08T07:31:13.062693Z 2 [Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-08T07:31:13.062710Z 2 [Note] (>MDL PRINT) Thread id is 2: 
2017-08-08T07:31:13.062725Z 2 [Note] (->MDL PRINT) DB_name is:test 
2017-08-08T07:31:13.062741Z 2 [Note] (-->MDL PRINT) OBJ_name is:a 
2017-08-08T07:31:13.062756Z 2 [Note] (--->MDL PRINT) Namespace is:TABLE 
2017-08-08T07:31:13.062768Z 2 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_READ_ONLY(SRO) 
2017-08-08T07:31:13.062781Z 2 [Note] (------>MDL PRINT) Mdl  duration is:MDL_TRANSACTION 
2017-08-08T07:31:13.062795Z 2 [Note] (------->MDL PRINT) Mdl  status is:GRANTED 
2017-08-08T07:31:13.062954Z 2 [Note] (acquire_lock)THIS MDL LOCK acquire ok!
2017-08-08T07:31:13.062974Z 2 [Note] (>MDL PRINT) Thread id is 2: 
2017-08-08T07:31:13.062989Z 2 [Note] (->MDL PRINT) DB_name is:test 
2017-08-08T07:31:13.063005Z 2 [Note] (-->MDL PRINT) OBJ_name is:b 
2017-08-08T07:31:13.063023Z 2 [Note] (--->MDL PRINT) Namespace is:TABLE 
2017-08-08T07:31:13.063039Z 2 [Note] (----->MDL PRINT) Mdl type is:MDL_SHARED_READ_ONLY(SRO) 
2017-08-08T07:31:13.063052Z 2 [Note] (------>MDL PRINT) Mdl  duration is:MDL_TRANSACTION 
2017-08-08T07:31:13.063065Z 2 [Note] (------->MDL PRINT) Mdl  status is:GRANTED 

总结一下这里的死锁

线程1 获得b的SW MDL LOCK-->线程2 获得a的SRO MDL LOCK,而拿不到b的SRO MDL LOCK(堵塞)-->线程1 拿不到a的SW MDL LOCK(堵塞)
这样 线程1和线程2都堵塞了,根据MDL LOCK死锁图的权重释放 线程1因为它都是DML操作。


五、处理

知道原因处理就相对简单了,备份表结构也加上 --single-transaction就好了,虽然备份表结构时间很短,但是高压力下也会出现死锁的情况。

上述内容就是MYSQL中一个特殊的MDL LOCK死锁的示例分析,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

MYSQL中一个特殊的MDL LOCK死锁的示例分析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

MySQL中next-key lock加锁范围的示例分析

这篇文章主要介绍MySQL中next-key lock加锁范围的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!前言某天,突然被问到 MySQL 的 next-key lock,我瞬间的反应就是:这都是啥啥啥?
2023-06-15

php中特殊运算符的示例分析

这篇文章将为大家详细讲解有关php中特殊运算符的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。三元运算符 ? :格式:表达式1 ? 表达式2 : 表达式3;如果表达式1的值为true,那么执行表达
2023-06-14

Shell编程中特殊变量的示例分析

这篇文章给大家分享的是有关Shell编程中特殊变量的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。$0 $# $n-->$[1..9] $* $@1、在shell中存在着一些特殊而又重要的变如:$1 $0
2023-06-09

MySQL数据库之Purge死锁问题的示例分析

小编给大家分享一下MySQL数据库之Purge死锁问题的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!Purge死锁场景说明Purge死锁说明表中存在记录(unique key) 10,20,30,40 (且有 自
2023-05-30

python多线程中互斥锁与死锁的示例分析

小编给大家分享一下python多线程中互斥锁与死锁的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!一、多线程间的资源竞争以下列task1(),task2()两个函数为例,分别将对全局变量num加一重复一千万次循环(
2023-06-29

Mysql中select加锁的示例分析

这篇文章将为大家详细讲解有关Mysql中select加锁的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。引言大家在面试中有没遇到面试官问你下面六句Sql的区别呢select * from tabl
2023-06-02

Linux中终端特殊设备文件的示例分析

这篇文章主要介绍Linux中终端特殊设备文件的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!终端是一种字符型设备,它有多种类型,通常使用tty来简称各种类型的终端设备。tty是Teletype的缩写。Tele
2023-06-12

Linux中特殊权限SUID SGID和SBIT的示例分析

这篇文章主要介绍Linux中特殊权限SUID SGID和SBIT的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、SUID,就重要的作用就是让其它用户在执行这个授有SUID的程序时拥有该程序拥有者的权限。就
2023-06-12

Linux中特殊符号与正则表达式的示例分析

这篇文章主要介绍了Linux中特殊符号与正则表达式的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。第1章 linux的特殊符号1.1 通配符 * {}1.1.1 含义
2023-06-09

Shell命令行中特殊字符与其转义的示例分析

这篇文章将为大家详细讲解有关Shell命令行中特殊字符与其转义的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。特殊符号及其转义大家都知道在一个shell命令是由命令名和它的参数组成的, 比如 ca
2023-06-09

编程热搜

目录