mysql批量更新方法

news2024/9/22 1:25:29

 

mysql批量更新方法

实验mysql版本为5.7.20  隔离级别为rr,加锁场景的问题在mysql8.0.18中为复现

方法一 replace into 批量更新

   原理:replace into table (col1,col2) values (x1,x2), 操作本质是对重复的记录先delete 后insert

https://img-blog.csdnimg.cn/img_convert/34d8ce2bc7a449d15b05259223723dfc.png

 缺点:1、如果更新的字段不全会将缺失的字段置为缺省值

            2、如果表中存在多个唯一键约束,那么会删除多行,造成数据丢失

            3、当有并发场景时,容易造成锁表,replace into流程死锁分析:http://mysql.taobao.org/monthly/2015/03/01/

字段缺失实验:

  1. CREATE TABLE `t_insert` (
  2.   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  3.   `i1` int(11) NOT NULL DEFAULT '0',
  4.   `i2` int(11) NOT NULL DEFAULT '0',
  5.   PRIMARY KEY (`id`),
  6.   UNIQUE KEY `idx_i1` (`i1`),
  7.   UNIQUE KEY `idx_i2` (`i2`) USING BTREE
  8. ) ENGINE=InnoDB AUTO_INCREMENT=1;
  9. mysql> select * from t_insert limit 4;
  10. +-----+-----+-----+
  11. | id  | i1  | i2  |
  12. +-----+-----+-----+
  13. | 107 | 102 | 211 |
  14. | 109 | 103 | 203 |
  15. | 111 |  10 |  99 |
  16. | 113 | 105 | 205 |
  17. +-----+-----+-----+
  18. 4 rows in set (0.00 sec)
  19. 没有设置i2的值
  20. mysql> replace into t_insert(id,i1) values (107,109);
  21. Query OK, 2 rows affected (0.04 sec)
  22. mysql> select * from t_insert limit 4;
  23. +-----+-----+-----+
  24. | id  | i1  | i2  |
  25. +-----+-----+-----+
  26. | 107 | 109 |   0 |     i2默认值为0
  27. | 109 | 103 | 203 |
  28. | 111 |  10 |  99 |
  29. | 113 | 105 | 205 |
  30. +-----+-----+-----+
  31. 4 rows in set (0.00 sec)

 丢失数据实验:

  1. mysql> describe t_insert;
  2. +-------+------------------+------+-----+---------+----------------+
  3. | Field | Type             | Null | Key | Default | Extra          |
  4. +-------+------------------+------+-----+---------+----------------+
  5. | id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
  6. | i1    | int(11)          | NO   | UNI | 0       |                |
  7. | i2    | int(11)          | NO   | UNI | 0       |                |
  8. +-------+------------------+------+-----+---------+----------------+
  9. 3 rows in set (0.12 sec)
  10. mysql> select * from t_insert;
  11. +-----+-----+-----+
  12. | id  | i1  | i2  |
  13. +-----+-----+-----+
  14. | 107 | 109 |   0 |
  15. | 109 | 103 | 203 |
  16. | 111 |  10 |  99 |
  17. | 113 | 105 | 205 |
  18. +-----+-----+-----+
  19. 4 rows in set (0.00 sec)
  20. mysql> replace into t_insert(id,i1,i2) values (107,103,205);
  21. Query OK, 4 rows affected (0.03 sec)
  22. 插入的数据存在3个冲突键,删掉3行,插入一行。造成数据丢失
  23. mysql> select * from t_insert;
  24. +-----+-----+-----+
  25. | id  | i1  | i2  |
  26. +-----+-----+-----+
  27. | 107 | 103 | 205 |
  28. | 111 |  10 |  99 |
  29. +-----+-----+-----+
  30. 2 rows in set (0.00 sec)

不指定id,无论是否有唯一键重复自增值就会自增实验:

  1. mysql> select * from t_insert;
  2. +----+----+----+
  3. | id | i1 | i2 |
  4. +----+----+----+
  5. |  4 |  1 |  1 |
  6. +----+----+----+
  7. 1 row in set (0.01 sec)
  8. mysql> SELECT Auto_increment FROM information_schema.TABLES WHERE Table_Schema='hi' AND table_name='t_insert';
  9. +----------------+
  10. | Auto_increment |
  11. +----------------+
  12. |              5 |
  13. +----------------+
  14. 1 row in set (0.00 sec)
  15. 插入重复键1,1
  16. mysql> replace into t_insert(i1,i2) values(1,1) ;
  17. Query OK, 2 rows affected (0.01 sec)
  18. mysql> select * from t_insert;
  19. +----+----+----+
  20. | id | i1 | i2 |
  21. +----+----+----+
  22. |  5 |  1 |  1 |
  23. +----+----+----+
  24. 1 rows in set (0.01 sec)
  25. mysql> SELECT Auto_increment FROM information_schema.TABLES WHERE Table_Schema='hi' AND table_name='t_insert';
  26. +----------------+
  27. | Auto_increment |
  28. +----------------+
  29. |              6 |
  30. +----------------+
  31. 1 row in set (0.00 sec)
  32. 插入新值
  33. mysql> replace into t_insert(i1,i2) values(2,2) ;
  34. Query OK, 1 row affected (0.01 sec)
  35. mysql> SELECT Auto_increment FROM information_schema.TABLES WHERE Table_Schema='hi' AND table_name='t_insert';
  36. +----------------+
  37. | Auto_increment |
  38. +----------------+
  39. |              7 |
  40. +----------------+
  41. 1 row in set (0.00 sec)
  42. mysql> replace into t_insert(i1,i2) values (110,220);
  43. Query OK, 2 rows affected (0.13 sec)

分析死锁前先介绍一些Mysql锁相关知识

https://img-blog.csdnimg.cn/img_convert/ce1bfe25fd4712591dc57e9e88fd4e23.png

在rr隔离级别中,普通的insert 插入前需要LOCK_INSERT_INTENTION 插入意向锁,插入意向锁是为了提供并发插入的性能,也是一种间隙锁,多个事务同时写入不同数据至同一索引范围(区间)内,并不需要等待其他事务完成,不会发生锁等待,同时插入意向锁是会被gap锁锁住的,在持有gap锁的情况下,新insert插入到这个范围时会获取这个范围的插入意向锁,此时如果这个范围有gap锁,则会阻塞当前插入,避免幻读

在rr的事务隔离级别下,insert on duplicate key、replace into与普通insert只插入意向锁和记录锁不同

insert只有存在主键冲突和唯一键冲突时会加 s next-key锁

insert on duplicate key 和replace into sql

如果存在主键上有冲突会插入排它next-key lock,没有冲突正常插入

如果唯一键上冲突会插入排它next-key lock,没有唯一键冲突会加gap锁(mysql5.7.20是这样,不管唯一键是什么类型都会加gap锁或next-key锁)

mysql可以设置以下Mysql参数监控事务加锁情况:

    set GLOBAL innodb_status_output_locks=ON; 开启锁监控

    set GLOBAL innodb_status_output=ON; 开启innodb标准监控

innodb status log中加锁含义:

记录锁(LOCK_REC_NOT_GAP): lock_mode X locks rec but not gap

间隙锁(LOCK_GAP): lock_mode X locks gap before rec

Next-key 锁(LOCK_ORNIDARY): lock_mode X

插入意向锁(LOCK_INSERT_INTENTION): lock_mode X locks gap before rec insert intention

heap no 1 PHYSICAL RECORD supremum 代表当前表中右边界

heap no 0 PHYSICAL RECORD inifimum 代表当前表中左边界

死锁实验:

CREATE TABLE `test` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`alias` int(11) NOT NULL,

`age` int(11) NOT NULL DEFAULT '0',

`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,

PRIMARY KEY (`id`),

UNIQUE KEY `u_idx_alias` (`alias`) USING BTREE

) ENGINE=InnoDB AUTO_INCREMENT=68 DEFAULT CHARSET=utf8;

  1. mysql> describe test;
  2. +-------+---------+------+-----+---------+----------------+
  3. | Field | Type    | Null | Key | Default | Extra          |
  4. +-------+---------+------+-----+---------+----------------+
  5. | id    | int(11) | NO   | PRI | NULL    | auto_increment |
  6. | alias | int(11) | NO   | UNI | NULL    |                |
  7. | age   | int(11) | NO   |     | 0       |                |
  8. +-------+---------+------+-----+---------+----------------+
  9. 3 rows in set (0.02 sec)
  10. session1:
  11. mysql> begin;replace into test values(22,22,11);
  12. Query OK, 0 rows affected (0.00 sec)
  13. session2,3执行完后在执行
  14. mysql> commit;
  15. Query OK, 0 rows affected (0.01 sec)
  16. session2:
  17. mysql> begin;replace into test values(23,23,11);
  18. Query OK, 0 rows affected (0.00 sec)
  19. session1 commit后
  20. Query OK, 1 row affected (12.22 sec)
  21. session3:
  22. mysql> begin;replace into test values(24,24,11);
  23. Query OK, 0 rows affected (0.00 sec)
  24. session1 commit后
  25. ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

session1未提交前 查看死锁日志show engine innodb status

https://img-blog.csdnimg.cn/img_convert/1aaeb2dbbc4750dfc6f66f7a3d568470.png

 加锁分析:线程1在插入主键索引的时候,由于无完全匹配记录,故不加锁;在插入记录的时候,无与意向锁不兼容的锁,直接插入主键索引;插入二次索引的时候,因无完全匹配记录,故在supremum记录上加Gap锁。

线程2在插入主键索引的时候,由于无完全匹配记录,故不加锁;在插入记录的时候,无与意向锁不兼容的锁,直接插入主键索引;插入二次索引的时候,因无完全匹配记录,故在supremum记录上加Gap锁,但在插入时因发现supremum记录上已经有其它线程的GAP锁,与自身插入意向锁冲突,故等待。

线程3与线程2类似。

session1提交后 查看死锁日志show engine innodb status;

加锁分析:线程2的插入意向锁等待线程3的Gap,而线程3的插入意向锁等待线程2的插入意向锁,出现死锁。

本地实验批量更新数据为1k,1w,10w下的更新时间

1k

https://img-blog.csdnimg.cn/img_convert/4931e61793e96f182a44b42f643755e4.png

1w

https://img-blog.csdnimg.cn/img_convert/30a1acbcdaa13a898978d3b8734896be.png

10w

https://img-blog.csdnimg.cn/img_convert/8808e78c67cb2d777a372d5f39bdf6f0.png

方法二 insert into 批量更新

   原理:insert into … on duplicate key update 这个语义的逻辑是,插入一行数据,如果碰到唯一键约束,就执行后面的更新语句。

https://img-blog.csdnimg.cn/img_convert/2bfdbf7aa9d04a29e60dc83eaf4b8c99.png

  缺点:  1、注意,如果有多个列违反了唯一性约束,就会按照索引的顺序,修改跟第一个

索引冲突的行

              2并发高的时候容易造成死锁

缺点1实验:

  1. mysql> select * from t_insert;
  2. +-----+-----+-----+
  3. | id  | i1  | i2  |
  4. +-----+-----+-----+
  5. | 105 | 101 | 209 |
  6. | 107 | 102 | 223 |
  7. | 123 | 103 | 227 |
  8. | 129 | 104 | 226 |
  9. +-----+-----+-----+
  10. 4 rows in set (0.00 sec)
  11. 插入130,102,202 但是存在102冲突,所以这里只更新107这一行
  12. mysql> INSERT INTO t_insert ( id, i1, i2 ) VALUES  (130,102,202) ON DUPLICATE KEY UPDATE i1 = VALUES ( i1 ), i2 = VALUES ( i2 );
  13. Query OK, 2 rows affected (0.09 sec)
  14. mysql> select * from t_insert;
  15. +-----+-----+-----+
  16. | id  | i1  | i2  |
  17. +-----+-----+-----+
  18. | 105 | 101 | 209 |
  19. | 107 | 102 | 202 |
  20. | 123 | 103 | 227 |
  21. | 129 | 104 | 226 |
  22. +-----+-----+-----+
  23. 4 rows in set (0.00 sec)

 死锁分析:

步骤一:设置Mysql参数,开启加锁输出

               set GLOBAL innodb_status_output_locks=ON;
               set GLOBAL innodb_status_output=ON;

步骤二:依次执行以下session中sql

session1:

  1. session1:
  2. mysql> CREATE TABLE `test` (
  3.       `id` int(11) NOT NULL AUTO_INCREMENT,
  4.        `alias` int(11) NOT NULL,
  5.       `age` int(11) NOT NULL DEFAULT '0',
  6.       PRIMARY KEY (`id`),
  7.       UNIQUE KEY `u_idx_alias` (`alias`) USING BTREE
  8.      ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  9. mysql> insert into test(alias,age) values(1,1),(7,7),(15,15);
  10. mysql> begin;insert into test(alias,age) value(12,12) on duplicate key update age=9;
  11. 等session2,3执行完后,再执行
  12. mysql> commit;
  13. session2:
  14. mysql>begin;insert into test(alias,age) value(13,13) on duplicate key update age=11;
  15. session3:
  16. mysql> begin;insert into test(alias,age) value(14,14) on duplicate key update age=11;
  17. Query OK, 0 rows affected (0.01 sec)
  18. session1 commit后:
  19. ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

session1 commit前:show engine innodb status

https://img-blog.csdnimg.cn/img_convert/6e9a2d710078a0017335e904f0804028.png

加锁分析:线程1在插入主键索引的时候,由于无完全匹配记录,故不加锁;在插入记录的时候,无与意向锁不兼容的锁,直接插入主键索引;插入二次索引的时候,因无完全匹配记录,故在7-15区间上加Gap锁。

线程2在插入主键索引的时候,由于无完全匹配记录,故不加锁;在插入记录的时候,无与意向锁不兼容的锁,直接插入主键索引;插入二次索引的时候,因无完全匹配记录,故在7-15区间上加Gap锁,但在插入意向锁时因发现7-15区间上已经有其它线程的GAP锁,与自身插入意向锁冲突,故等待。

线程3与线程2类似。

session1 commit后:show engine innodb status

https://img-blog.csdnimg.cn/img_convert/b0430ef026563706e97f3b087499a38d.png

加锁分析:线程1提交后线程2的插入意向锁等待线程3的Gap,而线程3的插入意向锁等待线程2的插入意向锁,故而死锁出现。

解决办法:1、在数据库表中只建立主键,不建立其他唯一索引

                  2、在有可能有并发事务执行的insert内容一样情况下不使用该语句

                  3、使用RC级别,RC隔离级别下不会有gap锁

                  4、升级到没有问题的版本,如8.0.18新版本

本地实验批量更新数据为1k,1w,10w下的更新时间

1k

https://img-blog.csdnimg.cn/img_convert/d49ec29208d44c0d2ebbabce50a1c53b.png

1w

https://img-blog.csdnimg.cn/img_convert/4e523e1b2916e65e2e5daed33471340d.png

10w

https://img-blog.csdnimg.cn/img_convert/6d7e0ee48424e056530abced6b7d0669.png

方法三 临时表 批量更新

原理:创建临时表,先更新临时表,然后从临时表中update

临时表生命周期只存在当前连接,连接关闭临时表会自动清除,不用临时表的时候最好显示删除掉,因为关闭连接/连接池的时候SQL Server才帮我们清除临时表了,但事实上连接池只有当程序重启的时候才清掉。在 binlog_format='row’的时候,临时表的操作不记录到 binlog

缺点:1、需要用户有临时表操作权限

           2不显示清除掉则可能导致tempdb占用磁盘空间非常大

          3设置 innodb_temp_data_file_path 选项,最好设定文件最大上限,超过上限时,需要生成临时表的SQL无法被执行

本地实验批量更新数据为1k,1w,10w下的更新时间

1k

https://img-blog.csdnimg.cn/img_convert/67488e6a4e829fe025139ad3958cd195.png

https://img-blog.csdnimg.cn/img_convert/8946429f7ca9fef1f8decedb57d2e167.png

1w

https://img-blog.csdnimg.cn/img_convert/b288c0ee700a806eac6287b8ca048262.png

https://img-blog.csdnimg.cn/img_convert/19850d560ae3ed73004ab67200709379.png

10w

https://img-blog.csdnimg.cn/img_convert/38080771a6a79b3c82dd38300ebe2d71.png

方法四 case when 批量更新

缺点: 1、拼接语句太长,当大于 max_allowed_packet限制时无法执行

            2、数据量少时执行速度还可以,多的时候就不行了,可读性差

本地实验批量更新数据为1k,1w,10w下的更新时间

1k

https://img-blog.csdnimg.cn/img_convert/634f4cbbaf183beb6c4a4bb89d111561.png

1w

https://img-blog.csdnimg.cn/img_convert/1ff52fa72df77c080518480944791eeb.png

10w

批量更新条数数据对比

方法

1K耗时(s)|影响行数

1w耗时(s)|影响行数

10w耗时(s)

replace into

0.216 | 2k

3.065 | 2w

7.02

insert into on duplicate

0.148 | 2k

0.557 | 2w

6.02

临时表更新

0.099 | 1k

0.626 | 1w

5.063

case when

0.216 | 1k

10.045 | 1w

10min54.54

总结:

根据实验结果,综合下来是更新速度 临时表 > insert into > replace into > case when

replace into和insert into在并发高的情况下都容易发生死锁,且在表中有多个唯一主键时会发生数据丢失的情况。replace into效率比insert into低的原因是,从操作上replace 比insert就多操作一步,当存在主键或唯一键冲突时,replace 是先删后插入,要重新维护索引,所以速度慢。而insert into是直接更新,更新对主键索引没有影响。所以当更新数据比较多的时候更建议使用insert into批量更新

临时表的使用场景应该是数据集比较小,用完马上清理,会话隔离。根据自己的机器配置,当在更新的数据量占用磁盘空间在可承受范围内的时候可以使用临时表来进行更新。在使用时需要有操作权限,并且需要设置临时文件的上限

case when批量更新数据比较小时可以使用,一旦数据量比较大拼接sql过长,可读性差,执行效率也低

如果想要用replace into和insert into 就需要考虑死锁的发生,将事务隔离级别设置成rc,没有gap锁,可以降低插入时发生死锁的概率,但是在存在唯一键或主键冲突时还是会加next-key锁(并没有实验)。建议像执行频率不高类似定时任务一天执行一次这种业务可以用insert into和replace into

还有一种批量更新的方式就是将n条批量更新语句放在同一事物中,降低事物的开销,合并binlog,redolog,降低刷磁盘的次数(还是要看自己配置的innodb_flush_log_at_trx_commit,和sync_binlog配置)。但事务只是保证acid,对每条sql的语义分析还是要执行n次,不过比执行多条更新语句要快很多

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/132911.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

特斯拉Model S及Model X 2023上半年交付,1月6日公布售价

特斯拉Model S及Model X终于快要交付了。 2022年12月30日,广州国际车展盛大开幕。众多车企带来了旗舰车型,让观众直呼太过瘾,其中,人流量爆火的莫过于特斯拉展台。此次,特斯拉携旗下S3XY家族重磅出击,全新车…

【C++基础】08:模板

模板 OVERVIEW模板一、函数模板1.func template基本使用:2.func template案例:数组排序3.函数与函数模板的区别&调用规则:4.func template的局限性:二、类模板1.类模板基本使用:2.类模板与函数模板的区别&#xff…

AOA估计中的MUSIC算法(Matlab代码实现)

目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨‍💻4 Matlab代码 💥1 概述 随着阵列信号处理技术的不断发展,到达角估计(Angle Of Arrival)的研究在移动通信系统中具有重要意义。通过分析经典MUSIC算法,…

golang 自定义命令行flag包简单使用

一、为什么需要使用golang自定义命令行 不恰当的比喻,当我们写了一个服务代码后,按照简单的思维,我们会在业务代码中将要连接的数据库 用户名、主机名、端口号、密码写死。 那么也就意味着我们启动该服务后都只能固定连接某一个数据库&#x…

etcd快速入门

etcd是什么 etcd是CoreOS团队于2013年6月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。 etcd内部采用raft协议作为一致性算法,etcd基于Go语言实现。 etcd作为服务发现系统,有以下的特点: 1.简单&#…

分享67个PHP源码,总有一款适合您

链接:https://pan.baidu.com/s/1MzKN0bLDRv0i290R2erMHQ?pwdbo2i 提取码:bo2i PHP源码 分享67个PHP源码,总有一款适合您 下面是文件的名字,我放了一些图片,文章里不是所有的图主要是放不下...,大家下载…

寒假每日一题W1D3——上课睡觉

题目描述 有 N 堆石子,每堆的石子数量分别为 a1,a2,…,aN。 你可以对石子堆进行合并操作,将两个相邻的石子堆合并为一个石子堆,例如,如果 a[1,2,3,4,5],合并第 2,3 堆石子,则石子堆集合变为 a[1,5,4,5]。…

【学习】backdoor attacks、Adversarial Attack on Images、Adversarial Attack on Audio

文章目录一、后门攻击backdoor attacks1、data poisoning2、backdoored PLM3、defenseONION4、后门攻击:绕过ONION防御5、摘要二、Adversarial Attack on Imagesone pixel attackdifferential evolution三、Adversarial Attack on Audio一、后门攻击backdoor attacks 什么是后…

进程的终止和等待

目录 进程终止 如何获取退出码呢? 进程退出方法有哪些? 对于进程退出,内核OS做了什么? 进程等待 为什么要进行进程等待? 如何进行进程等待? 什么是阻塞和非阻塞等待? 进程终止 对于进程…

飞依诺冲刺科创板上市:上半年出现亏损,因商业秘密纠纷被起诉

近日,飞依诺科技股份有限公司(下称“飞依诺”)在上海证券交易所递交招股书,准备在科创板上市。本次冲刺上市,飞依诺计划募资11.22亿元,将用于生产基地升级项目、新产品研发与总部基地建设项目、营销网络建设…

【Linux】一文掌握Linux基本指令(下)

本章命令大致总结命令功能cat打印文件内容echo打印文件内容> 输出重定向 >>追加重定向< 输入重定向 more 查看文本内容 less等价于morehead打印文本前n行tail 打印文本后n行 |管道date时间相关cal日历sort文本排序uniq相邻文本降重zip打包压缩unzip解包tar打包/解包…

蓝桥杯寒假集训第四天(全球变暖DFS)

没有白走的路&#xff0c;每一步都算数&#x1f388;&#x1f388;&#x1f388; 题目描述&#xff1a; 有一个正方形区域&#xff0c;里面有大陆和海洋&#xff0c;暂且用‘.’表示海洋&#xff0c;用‘#’表示大陆。我们把上下左右都连在一起的大陆称之为岛屿。但是随着气温…

07 来自于网友的 retrieveFileStream 的一个问题, 导致系统程序异常

前言 可以先参考前面一篇文章 retrieveFileStream 之后需要调用 completePendingCommand 否则业务代码会存在问题 retrieveFileStream 之后需要调用 completePendingCommand 否则业务代码会存在问题 这里的问题 主要是来自于 某 qq 交流群的网友 呵呵 当然 这里测试用例代码…

新鲜速递:Spring Data JPA 3.0快速入门、进阶到精通

第一章、安装Spring Data JPA 第一步&#xff0c;先确保你使用的是Spring Boot 3.0或以上环境&#xff0c;可以在pom.xml里加入Spring Data JPA依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-…

【ROS】—— ROS通信机制——话题通信(二)

文章目录前言1. 话题通信1.1 话题通讯理论模型1.2 话题通信基本操作&#xff08;C&#xff09;1.2.1 简单发布框架的实现1.2.2 发布逻辑的实现1.2.3 订阅方的实现1.3 话题通信基本操作&#xff08;python&#xff09;1.3.1 发布的实现1.3.2 订阅的实现1.4 话题通信自定义msg1.4…

五问补盲(五)| 想要长得好看又好用,补盲激光雷达应该怎么做?

上期&#xff0c;我们聊了好用的补盲激光雷达&#xff0c;得满足哪些条件&#xff1f; 好用是必备素质&#xff0c;属于补盲激光雷达的底线。好用之外&#xff0c;补盲激光雷达还有一种更直观的竞争力&#xff0c;那就是——外型。 有句话说的好&#xff0c;很多时候&#xff0…

2022跟学尚硅谷Maven入门(二)IDEA操作

2022跟学尚硅谷Maven入门二 IDEA操作第四章 使用Maven&#xff1a;IDEA环境第一节 创建父工程1.创建 Project2.开启自动导入第二节 配置 Maven 信息第三节 创建 Java 模块工程第四节 创建Web模块工程1.创建模块2.修改打包方式3.Web 设定4.借助IDEA生成web.xml5.设置 Web 资源的…

数据库,计算机网络、操作系统刷题笔记21

数据库&#xff0c;计算机网络、操作系统刷题笔记21 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;oracle…

基于thinkphp6搭建的 admin后台管理基础框架,方便快速进行二次开发

小牛Admin v2.1 完整代码下载地址&#xff1a;基于thinkphp6搭建的 admin后台管理基础框架 使用thinkphp6 layui 搭建的 admin后台管理基础框架&#xff0c;方便快速进行二次开发 该项目是在 http://www.xnadmin.cn/ 小牛Admin 开源项目的基础上进行个人优化的产物 运行环境…

Redis-用户签到UV统计

一、用户签到 1.1 BitMap用法 我们按月来统计用户签到信息&#xff0c;签到记录为1,未签到记录为0 把每一个bit位对应当月的每一天&#xff0c;形成了映射关系。用0和1表示业务状态&#xff0c;这种思路就称为位。Redis中是用利用string类型数据结构实现BitMap&#xff0c;因…