-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
59 lines (28 loc) · 36.4 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>MySQL基础</title>
<link href="/2024/05/22/MySQL%E5%9F%BA%E7%A1%80/"/>
<url>/2024/05/22/MySQL%E5%9F%BA%E7%A1%80/</url>
<content type="html"><![CDATA[<h1 id="MySQL"><a href="#MySQL" class="headerlink" title="MySQL"></a>MySQL</h1><h2 id="在console引入sql文件"><a href="#在console引入sql文件" class="headerlink" title="在console引入sql文件"></a>在console引入sql文件</h2><pre><code class="sql">source *****.sql</code></pre><h2 id="组合查询"><a href="#组合查询" class="headerlink" title="组合查询"></a>组合查询</h2><p><code>union</code></p><h2 id="常用函数"><a href="#常用函数" class="headerlink" title="常用函数"></a>常用函数</h2><h3 id="条件函数"><a href="#条件函数" class="headerlink" title="条件函数"></a>条件函数</h3><ol><li><code>if (条件, 条件为真 , 条件为假)</code></li><li><code>case when ... then ... when ... then ... else ... end</code></li></ol><h3 id="日期函数"><a href="#日期函数" class="headerlink" title="日期函数"></a>日期函数</h3><ol><li><code>year(data)</code> 取 年</li><li><code>month(data)</code> 取 月</li><li><code>day(data)</code> 取 日</li></ol><pre><code class="sql">-- MySQL日期时间处理函数-- 当前日期:2017-05-12SELECT NOW() FROM DUAL;-- 当前日期时间:2017-05-12 11:41:47-- 在MySQL里也存在和Oracle里类似的dual虚拟表:官方声明纯粹是为了满足select ... from...这一习惯问题,mysql会忽略对该表的引用。-- 那么MySQL中就不用DUAL了吧。SELECT NOW();-- 当前日期时间:2017-05-12 11:41:55-- 除了 now() 函数能获得当前的日期时间外,MySQL 中还有下面的函数:SELECT CURRENT_TIMESTAMP();-- 2017-05-15 10:19:31SELECT CURRENT_TIMESTAMP;-- 2017-05-15 10:19:51SELECT LOCALTIME();-- 2017-05-15 10:20:00SELECT LOCALTIME;-- 2017-05-15 10:20:10SELECT LOCALTIMESTAMP();-- 2017-05-15 10:20:21(v4.0.6)SELECT LOCALTIMESTAMP;-- 2017-05-15 10:20:30(v4.0.6)-- 这些日期时间函数,都等同于 now()。鉴于 now() 函数简短易记,建议总是使用 now()来替代上面列出的函数。 SELECT SYSDATE();-- 当前日期时间:2017-05-12 11:42:03-- sysdate() 日期时间函数跟 now() 类似,-- 不同之处在于:now() 在执行开始时值就得到了;sysdate() 在函数执行时动态得到值。-- 看下面的例子就明白了:SELECT NOW(), SLEEP(3), NOW();SELECT SYSDATE(), SLEEP(3), SYSDATE(); SELECT CURDATE();-- 当前日期:2017-05-12SELECT CURRENT_DATE();-- 当前日期:等同于 CURDATE()SELECT CURRENT_DATE;-- 当前日期:等同于 CURDATE() SELECT CURTIME();-- 当前时间:11:42:47SELECT CURRENT_TIME();-- 当前时间:等同于 CURTIME()SELECT CURRENT_TIME;-- 当前时间:等同于 CURTIME() -- 获得当前 UTC 日期时间函数SELECT UTC_TIMESTAMP(), UTC_DATE(), UTC_TIME()-- MySQL 获得当前时间戳函数:current_timestamp, current_timestamp()SELECT CURRENT_TIMESTAMP, CURRENT_TIMESTAMP();-- 2017-05-15 10:32:21 | 2017-05-15 10:32:21 -- MySQL 日期时间 Extract(选取) 函数SET @dt = '2017-05-15 10:37:14.123456';SELECT DATE(@dt);-- 获取日期:2017-05-15SELECT TIME('2017-05-15 10:37:14.123456');-- 获取时间:10:37:14.123456SELECT YEAR('2017-05-15 10:37:14.123456');-- 获取年份SELECT MONTH('2017-05-15 10:37:14.123456');-- 获取月份SELECT DAY('2017-05-15 10:37:14.123456');-- 获取日SELECT HOUR('2017-05-15 10:37:14.123456');-- 获取时SELECT MINUTE('2017-05-15 10:37:14.123456');-- 获取分SELECT SECOND('2017-05-15 10:37:14.123456');-- 获取秒SELECT MICROSECOND('2017-05-15 10:37:14.123456');-- 获取毫秒SELECT QUARTER('2017-05-15 10:37:14.123456');-- 获取季度SELECT WEEK('2017-05-15 10:37:14.123456');-- 20 (获取周)SELECT WEEK('2017-05-15 10:37:14.123456', 7);-- ****** 测试此函数在MySQL5.6下无效SELECT WEEKOFYEAR('2017-05-15 10:37:14.123456');-- 同week()SELECT DAYOFYEAR('2017-05-15 10:37:14.123456');-- 135 (日期在年度中第几天)SELECT DAYOFMONTH('2017-05-15 10:37:14.123456');-- 5 (日期在月度中第几天)SELECT DAYOFWEEK('2017-05-15 10:37:14.123456');-- 2 (日期在周中第几天;周日为第一天)SELECT WEEKDAY('2017-05-15 10:37:14.123456');-- 0SELECT WEEKDAY('2017-05-21 10:37:14.123456');-- 6(与dayofweek()都表示日期在周的第几天,只是参考标准不同,weekday()周一为第0天,周日为第6天)SELECT YEARWEEK('2017-05-15 10:37:14.123456');-- 201720(年和周) SELECT EXTRACT(YEAR FROM '2017-05-15 10:37:14.123456');SELECT EXTRACT(MONTH FROM '2017-05-15 10:37:14.123456');SELECT EXTRACT(DAY FROM '2017-05-15 10:37:14.123456');SELECT EXTRACT(HOUR FROM '2017-05-15 10:37:14.123456');SELECT EXTRACT(MINUTE FROM '2017-05-15 10:37:14.123456');SELECT EXTRACT(SECOND FROM '2017-05-15 10:37:14.123456');SELECT EXTRACT(MICROSECOND FROM '2017-05-15 10:37:14.123456');SELECT EXTRACT(QUARTER FROM '2017-05-15 10:37:14.123456');SELECT EXTRACT(WEEK FROM '2017-05-15 10:37:14.123456');SELECT EXTRACT(YEAR_MONTH FROM '2017-05-15 10:37:14.123456');SELECT EXTRACT(DAY_HOUR FROM '2017-05-15 10:37:14.123456');SELECT EXTRACT(DAY_MINUTE FROM '2017-05-15 10:37:14.123456');-- 151037(日时分)SELECT EXTRACT(DAY_SECOND FROM '2017-05-15 10:37:14.123456');-- 15103714(日时分秒)SELECT EXTRACT(DAY_MICROSECOND FROM '2017-05-15 10:37:14.123456');-- 15103714123456(日时分秒毫秒)SELECT EXTRACT(HOUR_MINUTE FROM '2017-05-15 10:37:14.123456');-- 1037(时分)SELECT EXTRACT(HOUR_SECOND FROM '2017-05-15 10:37:14.123456');-- 103714(时分秒)SELECT EXTRACT(HOUR_MICROSECOND FROM '2017-05-15 10:37:14.123456');-- 103714123456(日时分秒毫秒)SELECT EXTRACT(MINUTE_SECOND FROM '2017-05-15 10:37:14.123456');-- 3714(分秒)SELECT EXTRACT(MINUTE_MICROSECOND FROM '2017-05-15 10:37:14.123456');-- 3714123456(分秒毫秒)SELECT EXTRACT(SECOND_MICROSECOND FROM '2017-05-15 10:37:14.123456');-- 14123456(秒毫秒)-- MySQL Extract() 函数除了没有date(),time() 的功能外,其他功能一应具全。-- 并且还具有选取‘day_microsecond' 等功能。-- 注意这里不是只选取 day 和 microsecond,而是从日期的 day 部分一直选取到 microsecond 部分。 SELECT DAYNAME('2017-05-15 10:37:14.123456');-- Monday(返回英文星期)SELECT MONTHNAME('2017-05-15 10:37:14.123456');-- May(返回英文月份)SELECT LAST_DAY('2016-02-01');-- 2016-02-29 (返回月份中最后一天) SELECT LAST_DAY('2016-05-01');-- 2016-05-31 -- DATE_ADD(date,INTERVAL expr type) 从日期加上指定的时间间隔-- type参数可参考:http://www.w3school.com.cn/sql/func_date_sub.aspSELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 YEAR);-- 表示:2018-05-15 10:37:14.123456SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 QUARTER);-- 表示:2017-08-15 10:37:14.123456SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 MONTH);-- 表示:2017-06-15 10:37:14.123456SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 WEEK);-- 表示:2017-05-22 10:37:14.123456SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 DAY);-- 表示:2017-05-16 10:37:14.123456SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 HOUR);-- 表示:2017-05-15 11:37:14.123456SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 MINUTE);-- 表示:2017-05-15 10:38:14.123456SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 SECOND);-- 表示:2017-05-15 10:37:15.123456SELECT DATE_ADD('2017-05-15 10:37:14.123456',INTERVAL 1 MICROSECOND);-- 表示:2017-05-15 10:37:14.123457 -- DATE_SUB(date,INTERVAL expr type) 从日期减去指定的时间间隔SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 YEAR);-- 表示:2016-05-15 10:37:14.123456SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 QUARTER);-- 表示:2017-02-15 10:37:14.123456SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 MONTH);-- 表示:2017-04-15 10:37:14.123456SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 WEEK);-- 表示:2017-05-08 10:37:14.123456SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 DAY);-- 表示:2017-05-14 10:37:14.123456SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 HOUR);-- 表示:2017-05-15 09:37:14.123456SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 MINUTE);-- 表示:2017-05-15 10:36:14.123456SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 SECOND);-- 表示:2017-05-15 10:37:13.123456SELECT DATE_SUB('2017-05-15 10:37:14.123456',INTERVAL 1 MICROSECOND);-- 表示:2017-05-15 10:37:14.123455 -- 经特殊日期测试,DATE_SUB(date,INTERVAL expr type)可放心使用SELECT DATE_SUB(CURDATE(),INTERVAL 1 DAY);-- 前一天:2017-05-11SELECT DATE_SUB(CURDATE(),INTERVAL -1 DAY);-- 后一天:2017-05-13SELECT DATE_SUB(CURDATE(),INTERVAL 1 MONTH);-- 一个月前日期:2017-04-12SELECT DATE_SUB(CURDATE(),INTERVAL -1 MONTH);-- 一个月后日期:2017-06-12SELECT DATE_SUB(CURDATE(),INTERVAL 1 YEAR);-- 一年前日期:2016-05-12SELECT DATE_SUB(CURDATE(),INTERVAL -1 YEAR);-- 一年后日期:20178-06-12-- MySQL date_sub() 日期时间函数 和 date_add() 用法一致,并且可以用INTERNAL -1 xxx的形式互换使用;-- 另外,MySQL 中还有两个函数 subdate(), subtime(),建议,用 date_sub() 来替代。 -- MySQL 另类日期函数:period_add(P,N), period_diff(P1,P2)-- 函数参数“P” 的格式为“YYYYMM” 或者 “YYMM”,第二个参数“N” 表示增加或减去 N month(月)。-- MySQL period_add(P,N):日期加/减去N月。SELECT PERIOD_ADD(201705,2), PERIOD_ADD(201705,-2);-- 201707 20170503-- period_diff(P1,P2):日期 P1-P2,返回 N 个月。SELECT PERIOD_DIFF(201706, 201703);-- -- datediff(date1,date2):两个日期相减 date1 - date2,返回天数SELECT DATEDIFF('2017-06-05','2017-05-29');-- 7-- TIMEDIFF(time1,time2):两个日期相减 time1 - time2,返回 TIME 差值SELECT TIMEDIFF('2017-06-05 19:28:37', '2017-06-05 17:00:00');-- 02:28:37 -- MySQL日期转换函数SELECT TIME_TO_SEC('01:00:05'); -- 3605SELECT SEC_TO_TIME(3605);-- 01:00:05 -- MySQL (日期、天数)转换函数:to_days(date), from_days(days)SELECT TO_DAYS('0000-00-00'); -- NULL SELECT TO_DAYS('2017-06-05'); -- 736850SELECT FROM_DAYS(0); -- '0000-00-00' SELECT FROM_DAYS(736850); -- '2017-06-05' -- MySQL Str to Date (字符串转换为日期)函数:str_to_date(str, format) SELECT STR_TO_DATE('06.05.2017 19:40:30', '%m.%d.%Y %H:%i:%s');-- 2017-06-05 19:40:30SELECT STR_TO_DATE('06/05/2017', '%m/%d/%Y'); -- 2017-06-05SELECT STR_TO_DATE('2017/12/3','%Y/%m/%d') -- 2017-12-03SELECT STR_TO_DATE('20:09:30', '%h:%i:%s') -- NULL(超过12时的小时用小写h,得到的结果为NULL) -- 日期时间格式化SELECT DATE_FORMAT('2017-05-12 17:03:51', '%Y年%m月%d日 %H时%i分%s秒');-- 2017年05月12日 17时03分51秒(具体需要什么格式的数据根据实际情况来;小写h为12小时制;)SELECT TIME_FORMAT('2017-05-12 17:03:51', '%Y年%m月%d日 %H时%i分%s秒');-- 0000年00月00日 17时03分51秒(time_format()只能用于时间的格式化)-- STR_TO_DATE()和DATE_FORMATE()为互逆操作 -- MySQL 获得国家地区时间格式函数:get_format()-- MySQL get_format() 语法:get_format(date|time|datetime, 'eur'|'usa'|'jis'|'iso'|'internal'-- MySQL get_format() 用法的全部示例:SELECT GET_FORMAT(DATE,'usa'); -- '%m.%d.%Y' SELECT GET_FORMAT(DATE,'jis'); -- '%Y-%m-%d' SELECT GET_FORMAT(DATE,'iso'); -- '%Y-%m-%d' SELECT GET_FORMAT(DATE,'eur'); -- '%d.%m.%Y' SELECT GET_FORMAT(DATE,'internal'); -- '%Y%m%d' SELECT GET_FORMAT(DATETIME,'usa'); -- '%Y-%m-%d %H.%i.%s' SELECT GET_FORMAT(DATETIME,'jis'); -- '%Y-%m-%d %H:%i:%s' SELECT GET_FORMAT(DATETIME,'iso'); -- '%Y-%m-%d %H:%i:%s' SELECT GET_FORMAT(DATETIME,'eur'); -- '%Y-%m-%d %H.%i.%s' SELECT GET_FORMAT(DATETIME,'internal'); -- '%Y%m%d%H%i%s' SELECT GET_FORMAT(TIME,'usa'); -- '%h:%i:%s %p' SELECT GET_FORMAT(TIME,'jis'); -- '%H:%i:%s' SELECT GET_FORMAT(TIME,'iso'); -- '%H:%i:%s' SELECT GET_FORMAT(TIME,'eur'); -- '%H.%i.%s' SELECT GET_FORMAT(TIME,'internal'); -- '%H%i%s' -- MySQL 拼凑日期、时间函数:makdedate(year,dayofyear), maketime(hour,minute,second)SELECT MAKEDATE(2017,31); -- '2017-01-31' SELECT MAKEDATE(2017,32); -- '2017-02-01'SELECT MAKETIME(19,52,35); -- '19:52:35' -- MySQL 时区(timezone)转换函数:convert_tz(dt,from_tz,to_tz)SELECT CONVERT_TZ('2017-06-05 19:54:12', '+08:00', '+00:00'); -- 2017-06-05 11:54:12 -- MySQL (Unix 时间戳、日期)转换函数-- unix_timestamp(), unix_timestamp(date), from_unixtime(unix_timestamp), from_unixtime(unix_timestamp,format)-- 将具体时间时间转为timestampSELECT UNIX_TIMESTAMP();-- 当前时间的时间戳:1494815779SELECT UNIX_TIMESTAMP('2017-05-15');-- 指定日期的时间戳:1494777600SELECT UNIX_TIMESTAMP('2017-05-15 10:37:14');-- 指定日期时间的时间戳:1494815834 -- 将时间戳转为具体时间SELECT FROM_UNIXTIME(1494815834);-- 2017-05-15 10:37:14SELECT FROM_UNIXTIME(1494815834, '%Y年%m月%d日 %h时%分:%s秒');-- 获取时间戳对应的格式化日期时间 -- MySQL 时间戳(timestamp)转换、增、减函数SELECT TIMESTAMP('2017-05-15');-- 2017-05-15 00:00:00SELECT TIMESTAMP('2017-05-15 08:12:25', '01:01:01');-- 2017-05-15 09:13:26SELECT DATE_ADD('2017-05-15 08:12:25', INTERVAL 1 DAY);-- 2017-05-16 08:12:25SELECT TIMESTAMPADD(DAY, 1, '2017-05-15 08:12:25');-- 2017-05-16 08:12:25; MySQL timestampadd() 函数类似于 date_add()。 SELECT TIMESTAMPDIFF(YEAR, '2017-06-01', '2016-05-15');-- -1SELECT TIMESTAMPDIFF(MONTH, '2017-06-01', '2016-06-15');-- -11SELECT TIMESTAMPDIFF(DAY, '2017-06-01', '2016-06-15');-- -351SELECT TIMESTAMPDIFF(HOUR, '2017-06-01 08:12:25', '2016-06-15 00:00:00');-- -8432SELECT TIMESTAMPDIFF(MINUTE, '2017-06-01 08:12:25', '2016-06-15 00:00:00');-- -505932SELECT TIMESTAMPDIFF(SECOND, '2017-06-01 08:12:25', '2016-06-15 00:00:00');-- -30355945</code></pre><p><a href="https://blog.csdn.net/hu1010037197/article/details/115391335">https://blog.csdn.net/hu1010037197/article/details/115391335</a></p><h3 id="MySQL-TIMESTAMPDIFF函数简介"><a href="#MySQL-TIMESTAMPDIFF函数简介" class="headerlink" title="MySQL TIMESTAMPDIFF函数简介"></a>MySQL TIMESTAMPDIFF函数简介</h3><p>下面说明了<code>TIMESTAMPDIFF</code>函数的语法。</p><pre><code class="sql">TIMESTAMPDIFF(unit,begin,end);</code></pre><p><code>TIMESTAMPDIFF</code>函数返回<code>begin-end</code>的差值,其中<code>begin</code>和<code>end</code>是<a href="http://www.yiibai.com/mysql/date.html">DATE</a>或<a href="http://www.yiibai.com/mysql/datetime.html">DATETIME</a>表达式。</p><p><code>TIMESTAMPDIFF</code>函数允许其参数具有混合类型,例如,<code>begin</code>是<code>DATE</code>值,<code>end</code>可以是<code>DATETIME</code>值。 如果使用<code>DATE</code>值,则<code>TIMESTAMPDIFF</code>函数将其视为时间部分为<code>“00:00:00”</code>的<code>DATETIME</code>值。</p><p><code>unit</code>参数是确定(<code>end-begin</code>)的结果的单位,表示为整数。 以下是有效单位:</p><ul><li>MICROSECOND</li><li>SECOND</li><li>MINUTE</li><li>HOUR</li><li>DAY</li><li>WEEK</li><li>MONTH</li><li>QUARTER</li><li>YEAR=</li></ul><h2 id="文本函数"><a href="#文本函数" class="headerlink" title="文本函数"></a>文本函数</h2><p><img src="/MySQL.assets/4EF7B5DAE69AD54DE81C49D58020D7A4.png" alt="图片说明"></p><h2 id="SQL窗口函数"><a href="#SQL窗口函数" class="headerlink" title="SQL窗口函数"></a>SQL窗口函数</h2><pre><code class="sql"><窗口函数> over (partition by <用于分组的列名> order by <用于排序的列名>)</code></pre><h2 id="with…as"><a href="#with…as" class="headerlink" title="with…as"></a>with…as</h2><p>简化子查询的书写(创建临时表)</p><pre><code class="powershell">mysql> select * from account where money = 5000;+-----------+----------+---------+| accountId | name | money |+-----------+----------+---------+| 1 | tom | 5000.00 || 2 | lucy | 5000.00 || 3 | zhangsan | 5000.00 |+-----------+----------+---------+3 rows in set (0.00 sec)mysql> with t1 as (select * from account where money = 5000) -> select * from t1 where accountId = 1;+-----------+------+---------+| accountId | name | money |+-----------+------+---------+| 1 | tom | 5000.00 |+-----------+------+---------+1 row in set (0.00 sec)</code></pre><h1 id="ALTER-表"><a href="#ALTER-表" class="headerlink" title="ALTER 表"></a>ALTER 表</h1><pre><code class="sql">alter table user_info add school varchar(15) after level;# 增加列在某列之后# alter` `table` `增加的表格 ``add` `增加列的名称 数据类型 位置(``after` `level` `在``level` `之后)</code></pre><pre><code class="sql">alter table user_info change job profession varchar(10);# 更换列的名称及数据类型# alter table user_info change 原列名 修改列名 修改数据类型</code></pre><pre><code class="sql">alter table user_info modify achievement int(11) default 0;# 更改数据类型与约束# alter table 表名 modify 修改列名称 数据类型 默认值等</code></pre><pre><code class="sql"># 删除列alter table 表名 drop column 列名;</code></pre><pre><code class="sql"># 修改表名alter table 表名 rename 新表名;</code></pre><h1 id="MySQL字符编码"><a href="#MySQL字符编码" class="headerlink" title="MySQL字符编码"></a>MySQL字符编码</h1><p><img src="/MySQL.assets/image-20220212170233406.png" alt="image-20220212170233406"></p><p>MySQL 字符编码集中有两套 UTF-8 编码实现:</p><ul><li><strong><code>utf8</code></strong> : <code>utf8</code>编码只支持<code>1-3</code>个字节 。 在 <code>utf8</code> 编码中,中文是占 3 个字节,其他数字、英文、符号占一个字节。但 emoji 符号占 4 个字节,一些较复杂的文字、繁体字也是 4 个字节。</li><li><strong><code>utf8mb4</code></strong> : UTF-8 的完整实现,<strong>正版</strong>!最多支持使用 4 个字节表示字符,因此,可以用来存储 emoji 符号。</li></ul><p>因此,如果你需要存储<code>emoji</code>类型的数据或者一些比较复杂的文字、繁体字到 MySQL 数据库的话,数据库的编码一定要指定为<code>utf8mb4</code> 而不是<code>utf8</code> ,要不然存储的时候就会报错了</p><p><strong>建议默认使用<code>utf8mb4</code></strong></p><h1 id="MySQL引擎"><a href="#MySQL引擎" class="headerlink" title="MySQL引擎"></a>MySQL引擎</h1><p><img src="/MySQL.assets/image-20220212171434185-16446577102162.png" alt="image-20220212171434185"></p><h2 id="MyISAM和InnoDB的区别"><a href="#MyISAM和InnoDB的区别" class="headerlink" title="MyISAM和InnoDB的区别"></a>MyISAM和InnoDB的区别</h2><p><strong>1.是否支持行级锁</strong></p><p>MyISAM 只有表级锁(table-level locking),而 InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。</p><p>也就说,MyISAM 一锁就是锁住了整张表,这在并发写的情况下是多么滴憨憨啊!这也是为什么 InnoDB 在并发写的时候,性能更牛皮了!</p><p><strong>2.是否支持事务</strong></p><p>MyISAM 不提供事务支持。</p><p>InnoDB 提供事务支持,具有提交(commit)和回滚(rollback)事务的能力。</p><p><strong>3.是否支持外键</strong></p><p>MyISAM 不支持,而 InnoDB 支持。</p><p>🌈拓展一下:</p><ul><li>一般我们也是不建议在数据库层面使用外键的,应用层面可以解决。不过,这样会对数据的一致性造成威胁。具体要不要使用外键还是要根据你的项目来决定。</li></ul><p><strong>4.是否支持数据库异常崩溃后的安全恢复</strong></p><p>MyISAM 不支持,而 InnoDB 支持。</p><p>使用 InnoDB 的数据库在异常崩溃后,数据库重新启动的时候会保证数据库恢复到崩溃前的状态。这个恢复的过程依赖于 <code>redo log</code> 。</p><p>🌈 拓展一下:</p><ul><li>MySQL InnoDB 引擎使用 <strong>redo log(重做日志)</strong> 保证事务的<strong>持久性</strong>,使用 <strong>undo log(回滚日志)</strong> 来保证事务的<strong>原子性</strong>。</li><li>MySQL InnoDB 引擎通过 <strong>锁机制</strong>、<strong>MVCC</strong> 等手段来保证事务的隔离性( 默认支持的隔离级别是 <strong><code>REPEATABLE-READ</code></strong> )。</li><li>保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障。</li></ul><p><strong>5.是否支持 MVCC</strong></p><p>MyISAM 不支持,而 InnoDB 支持。</p><p>讲真,这个对比有点废话,毕竟 MyISAM 连行级锁都不支持。</p><p><strong>MVCC 可以看作是行级锁的一个升级,可以有效减少加锁操作,提供性能</strong></p><h1 id="InnoDB锁"><a href="#InnoDB锁" class="headerlink" title="InnoDB锁"></a>InnoDB锁</h1><p><strong>MyISAM 和 InnoDB 存储引擎使用的锁:</strong></p><ul><li>MyISAM 采用表级锁(table-level locking)。</li><li>InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁</li></ul><p><strong>表级锁和行级锁对比:</strong></p><ul><li><strong>表级锁:</strong> MySQL 中锁定 <strong>粒度最大</strong> 的一种锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。其锁定粒度最大,触发锁冲突的概率最高,并发度最低,MyISAM 和 InnoDB 引擎都支持表级锁。</li><li><strong>行级锁:</strong> MySQL 中锁定 <strong>粒度最小</strong> 的一种锁,只针对当前操作的行进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,<strong>会出现死锁</strong>。</li></ul><p><strong>InnoDB 存储引擎的锁的算法有三种:</strong></p><ul><li><code>Record lock</code>:记录锁,<strong>单个行</strong>记录上的锁</li><li><code>Gap lock</code>:间隙锁,<strong>锁定一个范围,不包括记录本身</strong></li><li><code>Next-key lock</code>:record+gap 临键锁,<strong>锁定一个范围,包含记录本身</strong></li></ul><h1 id="事务"><a href="#事务" class="headerlink" title="事务"></a>事务</h1><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>事务是用户定义的一组数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位</p><h2 id="何为-ACID-特性呢?"><a href="#何为-ACID-特性呢?" class="headerlink" title="何为 ACID 特性呢?"></a>何为 ACID 特性呢?</h2><ol><li><strong>原子性</strong>(<code>Atomicity</code>) : 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;</li><li><strong>一致性</strong>(<code>Consistency</code>): 执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;</li><li><strong>隔离性</strong>(<code>Isolation</code>): 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;</li><li><strong>持久性</strong>(<code>Durability</code>): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。</li></ol><h2 id="数据事务的实现原理呢?"><a href="#数据事务的实现原理呢?" class="headerlink" title="数据事务的实现原理呢?"></a>数据事务的实现原理呢?</h2><p>我们这里以 MySQL 的 InnoDB 引擎为例来简单说一下</p><ul><li>MySQL InnoDB 引擎使用 <strong>redo log(重做日志)</strong> 保证事务的<strong>持久性</strong>,使用 <strong>undo log(回滚日志)</strong> 来保证事务的<strong>原子性</strong>。</li><li>MySQL InnoDB 引擎通过 <strong>锁机制</strong>、<strong>MVCC</strong> 等手段来保证事务的隔离性( 默认支持的隔离级别是 <strong><code>REPEATABLE-READ</code></strong> )</li><li>保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障</li></ul><h2 id="并发问题"><a href="#并发问题" class="headerlink" title="并发问题"></a>并发问题</h2><ul><li><strong>脏读(Dirty read):</strong> 当一个事务正在访问数据并且对数据进行了修改,而这种修改还<strong>没有提交</strong>到数据库中,这时另外一个事务也<strong>访问了这个未提交数据</strong>,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的</li><li><strong>丢失修改(Lost to modify):</strong> 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 例如:事务 1 读取某表中的数据 A=20,事务 2 也读取 A=20,事务 1 修改 A=A-1,事务 2 也修改 A=A-1,最终结果 A=19,事务 1 的修改被丢失</li><li><strong>不可重复读(Unrepeatable read):</strong> 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读</li><li><strong>幻读(Phantom read):</strong> 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。</li></ul><p><strong>不可重复读和幻读区别:</strong></p><p>不可重复读的重点是<strong>修改</strong>比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于<strong>新增</strong>或者<strong>删除</strong>比如多次读取一条记录发现记录增多或减少了</p><h3 id="事务隔离级别有哪些"><a href="#事务隔离级别有哪些" class="headerlink" title="事务隔离级别有哪些?"></a>事务隔离级别有哪些?</h3><p>SQL 标准定义了四个隔离级别:</p><ul><li><strong>READ-UNCOMMITTED(读取未提交):</strong> 最低的隔离级别,允许读取尚未提交的数据变更,<strong>可能会导致脏读、幻读或不可重复读</strong>。</li><li><strong>READ-COMMITTED(读取已提交):</strong> 允许读取并发事务已经提交的数据,<strong>可以阻止脏读,但是幻读或不可重复读仍有可能发生</strong>。</li><li><strong>REPEATABLE-READ(可重复读):</strong> 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,<strong>可以阻止脏读和不可重复读,但幻读仍有可能发生</strong>。</li><li><strong>SERIALIZABLE(可串行化):</strong> 最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,<strong>该级别可以防止脏读、不可重复读以及幻读</strong>。</li></ul><table><thead><tr><th align="center">隔离级别</th><th align="center">脏读</th><th align="center">不可重复读</th><th align="center">幻读</th></tr></thead><tbody><tr><td align="center">READ-UNCOMMITTED</td><td align="center">√</td><td align="center">√</td><td align="center">√</td></tr><tr><td align="center">READ-COMMITTED</td><td align="center">×</td><td align="center">√</td><td align="center">√</td></tr><tr><td align="center">REPEATABLE-READ</td><td align="center">×</td><td align="center">×</td><td align="center">√</td></tr><tr><td align="center">SERIALIZABLE</td><td align="center">×</td><td align="center">×</td><td align="center">×</td></tr></tbody></table><h3 id="MySQL-的默认隔离级别是什么"><a href="#MySQL-的默认隔离级别是什么" class="headerlink" title="MySQL 的默认隔离级别是什么?"></a>MySQL 的默认隔离级别是什么?</h3><p>MySQL InnoDB 存储引擎的默认支持的隔离级别是 <strong>REPEATABLE-READ(可重读)</strong>。我们可以通过<code>SELECT @@tx_isolation;</code>命令来查看,MySQL 8.0 该命令改为<code>SELECT @@transaction_isolation</code></p><p><strong>MySQL InnoDB 的 REPEATABLE-READ(可重读)并不保证避免幻读,需要应用使用加锁读来保证。而这个加锁度使用到的机制就是 Next-Key Locks</strong></p><p>因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是 <strong>READ-COMMITTED(读取提交内容)</strong> ,但是你要知道的是 InnoDB 存储引擎默认使用 <strong>REPEATABLE-READ(可重读)</strong> 并不会有任何性能损失</p><p>InnoDB 存储引擎在 <strong>分布式事务</strong> 的情况下一般会用到 <strong>SERIALIZABLE(可串行化)</strong> 隔离级别</p><h1 id="JDBC异常"><a href="#JDBC异常" class="headerlink" title="JDBC异常"></a>JDBC异常</h1><ul><li><code>java.sql.SQLException</code>——这是JDBC异常的基类</li><li><code>java.sql.BatchUpdateException</code>——当批处理操作执⾏失败的时候可能会抛出这个异常。这取决 于具体的JDBC驱动的实现,它也可能直接抛出基类异常<code>java.sql.SQLException</code></li><li><code>java.sql.SQLWarning</code>——SQL操作出现的警告信息</li><li><code>java.sql.DataTruncation</code>——字段值由于某些⾮正常原因被截断了(不是因为超过对应字段类型的 ⻓度限制)</li></ul><h1 id="SQL执行顺序"><a href="#SQL执行顺序" class="headerlink" title="SQL执行顺序"></a>SQL执行顺序</h1><p><img src="/MySQL.assets/format,png.png" alt="SQL查询语句的执行顺序解析"></p><p><img src="/MySQL.assets/format,png-16451044623752.png" alt="SQL查询语句的执行顺序解析"></p><h1 id="慢SQL"><a href="#慢SQL" class="headerlink" title="慢SQL"></a>慢SQL</h1><p>顾名思义,就是执行速度很慢的SQL(运行速度达到秒级别),当慢SQL的数量达到一定程度时,会严重影响系统的性能</p><h2 id="分析与优化"><a href="#分析与优化" class="headerlink" title="分析与优化"></a>分析与优化</h2><ol><li>开启慢查询日志,设置超过几秒为慢SQL,抓取慢SQL</li></ol><pre><code>1. 开启日志 ```bash (1)设置开启:SET GLOBAL slow_query_log = 1; #默认未开启,开启会影响性能,mysql重启会失效 (2)查看是否开启:SHOW VARIABLES LIKE '%slow_query_log%'; (3)设置阈值:SET GLOBAL long_query_time=3; (4)查看阈值:SHOW 【GLOBAL】 VARIABLES LIKE 'long_query_time%'; #重连或新开一个会话才能看到修改值 (5)通过修改配置文件my.cnf永久生效,在[mysqld]下配置: [mysqld] slow_query_log = 1; #开启 slow_query_log_file=/var/lib/mysql/atguigu-slow.log #慢日志地址,缺省文件名host_name-slow.log # windows 所在位置 C:/ProgramData/MySQL/MySQL Server 8.0/Data long_query_time=3; #运行时间超过该值的SQL会被记录,默认值>10 log_output=FILE ```2. 查看日志 ```bash 查看慢查询日志记录数:SHOW GLOBAL STATUS LIKE '%Slow_queries%'; ```3. 搭建分析工具 mysqldumpslow</code></pre><ol start="2"><li><p>通过<code>explain</code>对慢SQL分析(重点)</p><pre><code class="mysql"># 例子explain select sleep(4);# 之后mysql会将SQL的执行情况展示出来</code></pre><p><a href="https://www.cnblogs.com/zjxiang/p/9160564.html">https://www.cnblogs.com/zjxiang/p/9160564.html</a></p></li><li><p><code>show profile</code>查询SQL在Mysql服务器里的执行细节和<strong>生命周期情况</strong>(重点)</p><pre><code class="mysql"># 查询是否支持select @@have_profiling;# 查询是否开启select @@profiling;# 只开启当前会话set profiling=1; # 查看指令执行耗时show profiles;# 查看指令分步骤耗时show profile for query query_id;# TIP:# Sending data状态表示MySQL线程开始访问数据行并把结果返回给客户端,由于在Sending data状态需要读写磁盘,故一般时间最长# 查看指令资源消耗show profile all for query query_id;# trace 查看优化器的执行计划set optimizer_trace="enabled=on" # 设置trace打开end_markers_in_json=on # 设置格式为jsonset optimizer_trace_max_mem_size=10000 # 设置最大内存数</code></pre></li><li><p>开启全局日志(另一种日志)</p><p>只在测试环境用,别在生产环境用,会记录所有使用过的SQL</p><p>开启:</p><pre><code class="bash">开启:会将sql记录到mysql库的general_log表set global general_log=1;set global log_output='TABLE';配置文件的方式:在my.cnf中配置general_log=1 #开启general_log_file=/path/logfile #记录日志文件的路径log_output=FILE #输出格式</code></pre><p>查看</p><pre><code class="sql">select * from mysql.general_log;</code></pre></li></ol>]]></content>
<categories>
<category> 数据库 </category>
</categories>
<tags>
<tag> MySQL </tag>
</tags>
</entry>
<entry>
<title>Hello World</title>
<link href="/2024/05/21/hello-world/"/>
<url>/2024/05/21/hello-world/</url>
<content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><pre><code class="bash">$ hexo new "My New Post"</code></pre><p>More info: <a href="https://hexo.io/docs/writing.html">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><pre><code class="bash">$ hexo server</code></pre><p>More info: <a href="https://hexo.io/docs/server.html">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><pre><code class="bash">$ hexo generate</code></pre><p>More info: <a href="https://hexo.io/docs/generating.html">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><pre><code class="bash">$ hexo deploy</code></pre><p>More info: <a href="https://hexo.io/docs/one-command-deployment.html">Deployment</a></p>]]></content>
<categories>
<category> Hello Hexo </category>
</categories>
<tags>
<tag> hexo </tag>
<tag> blog </tag>
</tags>
</entry>
</search>