08_MySQL笔记-锁-常量-DISTINCT-DESC-WHERE

Posted mycpen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了08_MySQL笔记-锁-常量-DISTINCT-DESC-WHERE相关的知识,希望对你有一定的参考价值。

文章目录


个人博客
https://blog.csdn.net/cPen_web


Session是什么?
	会话:创建一个连接 --> 建立了一个会话

长连接:一直的连着不断开,除非人为的关闭 --> mysql和ssh连接
短连接:先建立3次握手 --> 传输数据 --> 四次断开

root@test mysql>show processlist;			#注:查看有哪些人连接(几个session)
#注:一个连接里面创建很多的事务

buffer:缓存
	仍然是一个临时存放数据的地方(写操作)
	内存 --> buffer --> 磁盘
cache:缓存
	读操作 临时存放数据的地方
	磁盘 --> cache --> 内存

缓存的作用确实起到加速的作用,特别是cache
减少系统CPU和进程、内存资源的消耗
本质上,从进程的调度来思考

作用:节约资源;频繁io影响系统性能(操作系统层面分析;进程方面考虑)
数据的修改都是在内存中进行的(缓冲池)

缓冲池大小 最大 内存的80%
page页
buffer pool是mysql内部的的缓存池,相当于mysql内部存放数据的地方
buffer pool最大的大小可以到达整个物理内存的80%

root@(none) mysql>show variables like "innodb_buffer_pool_size";
| Variable_name           | Value     |
| innodb_buffer_pool_size | 536870912 |
Buffer Pool LRU Algorithm
LRU算法
	最近最少使用算法
	LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰

页化(page)(内存里的单位) 
	mysql里1页 16k
	磁盘 文件系统的块 默认4k
脏读
	mysql里不允许脏读,因为事务是隔离的
其它用户(事务)不能查看当前用户(事务)所做的DML操作的结果。这叫做不允许脏读(dirty read)
脏读:一个事务读到了另一个事务未提交的数据
已修改但未提交的数据叫做赃数据(注:脏数据在内存中)

表中受影响的行被锁定,其它用户(事务)不能在受影响的行上修改数据

锁
	颗粒度
		表锁
		行锁		innodb
	行为
		读锁		备份的时候
		写锁		lock tables t1 write;
		共享锁
		排他锁
为什么要加锁?
	大并发情况下,为了保持数据的一致性。需要对资源进行管控,需要使用锁,解决资源竞争的问题

死锁
	死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
	如何解决死锁?
		1 .使用另外的程序来检查是否存在死锁,干预,杀死某些进程
		2 .设计程序的时候,考虑获得条件的先后顺序
		3 .队列
活锁
	活锁指的是任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试—失败—尝试—失败的过程。处于活锁的实体是在不断的改变状态,活锁有可能自行解开。

读锁 --> 读数据的时候,给某行加一个锁		备份的时候
写锁 --> 写数据的时候,给某行加一个锁		lock tables t1 write;

意向锁
共享锁 --> 读锁
互斥锁 --> 写锁
表锁
READ:当前会话和其它会话都可以读表,但是不能修改表
WRITE:当前会话可以读写表,但是其它会话既不能读也不能写
#示例:锁表 (写锁)
root@test mysql>lock tables t1 write;
	#注:写锁是互斥锁,其他的会话不能查和写。写锁会影响到并发

#示例:把锁释放
root@test mysql>unlock tables;

#示例:查询时加锁 添加共享锁
root@test mysql>select * from t1 lock in share mode;

事务的4个问题

并发事务的4个问题
	脏读
	不可重复度
		修改了数据	update
	幻读
		记录是不一样	insert或者delete
	丢失更新

事务的4个隔离级别

	每个事务都有一个隔离级别(isolation level),它规定了并发运行的两个事务之间是否允许发生上面的问题。
	MySQL有4种事务隔离级别:
repeatable read		可重复读  默认级别
read committed		读已提交
read uncommitted	读未提交
serializable		串行化
查看数据库及当前会话的事务隔离级别(2种方法)
	SELECT @@GLOBAL.tx_isolation, @@tx_isolation;
	root@test mysql>SELECT @@GLOBAL.tx_isolation, @@tx_isolation;
	root@test mysql>show variables like "tx_isolation";

在配置文件中指定数据库的事务隔离级别
[mysqld] 
transaction-isolation = REPEATABLE-READ
#示例:备份jd库
[root@cPen ~]# mysqldump -ucali -p'123456' jd >jd.sql
#示例:备份所有的数据库
[root@cPen ~]# mysqldump -h 192.168.31.165 -ucali -p'123456' --all-databases >jd.sql
#示例:备份TENNIS库
[root@cPen ~]# mysqldump -uroot -p'Sanchuang123#' --databases TENNIS >tennis.sql
root@test mysql>drop database TENNIS;					#注:删除TENNIS库
#示例:导入TENNIS库
[root@cPen ~]# mysql -uroot -p'Sanchuang123#' <tennis.sql 
#注:备份还原的时候 会锁表

事务处理 在Python代码里的经典应用

参考:https://www.runoob.com/python3/python3-mysql.html

Python pymysql操纵MySQL时,需要commit提交
	#注:自动开启一个事务,自己需要敲db.commit()提交  利用事务 来处理往数据库里写数据
[root@cPen ~]# vim sc.py 
import pymysql
# 打开数据库连接
db = pymysql.connect(host="192.168.31.165", user="cali", passwd="123456", db="test")
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# SQL 插入语句
sql = """INSERT INTO t1(id,name)
         VALUES (300, 'yiyiqiang')"""
try:
   # 执行sql语句
   cursor.execute(sql)
   # 提交到数据库执行
   db.commit()
except:
   # 如果发生错误则回滚
   db.rollback()
# 关闭数据库连接
db.close()
[root@cPen ~]# python3 sc.py 
Python代码里,自动开启commit --> autocommit的开启

conn = pymysql.connect(
   user = 'cali',
   passwd = '123456',
   db = 'test',
   host = '127.0.0.1',
   port = 3306,
   charset = 'utf8',
   autocommit = True    # 自动提交确认
)
SELECT语句返回的结果叫做结果集(RESULTSET)。它是一个表格	#注:是一个元组

结果集的列标题由SELECT子句中的列名或表达式决定,大小写和列名的大小写保持一致。列标题是左对齐的

#示例:Python从数据库里取出来
root@(none) mysql>grant all on *.* to 'cali'@'%' identified by '123456';

>>> import pymysql
>>> db = pymysql.connect(
...     host = "192.168.31.165",
...     user = "cali",
...     passwd = "123456"
... )
>>> cursor.execute("use test")
>>> sql = "select * from t1";
>>> cursor.execute(sql)
>>> data = cursor.fetchall()
>>> type(data)
<class 'tuple'>
>>> print(data)
((1, None), (2, 'zhangheng'), (100, 'zhang'), (300, 'yiyiqiang'), (300, 'yiyiqiang'), (300, 'yiyiqiang'))
>>> data[1]
(2, 'zhangheng')
>>> data[1][0]
2
root@test mysql>desc totals;				#注:查看表结构

@@sql_mode	这个变量的作用:就是规定了在mysql里我们写sql语句的时候,哪些是允许 哪些是不允许的操作,也就是一些规矩
root@test mysql>select @@sql_mode;
+------------------------------------------------------------------------------------------------------------------------+
| @@sql_mode                                                                                                             |
+------------------------------------------------------------------------------------------------------------------------+
| STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
global	全局变量
session	当前会话里的变量 --> 局部变量
	全局设置影响从那时起新连接的所有客户端,设置SESSION变量只影响当前的客户端
# MySQL是多线程的服务
[root@cPen ~]# yum install psmisc -y
[root@cPen ~]# pstree -p|grep mysql			#注:pstree  查看进程树
           |-mysqld_safe(1056)---mysqld(1270)-+-mysqld(1502)
           |                                  |-mysqld(1550)
           |                                  |-mysqld(1551)
           |                                  |-mysqld(1552)
#注:-p	显示pid号

常量

字面量(常量)
字面量literal:就是一个不变的、固定的值。字面量总是有一个数据类型 
字符串字面量:使用双引号或者单引号括起来的字母或数字的组合
强烈建议使用日期字面量时,采用字符串的写法,并且年部分写4位数字
强烈建议使用时间字面量时,采用字符串的写法,并且冒号作为分隔符 
日期时间字面量和时间戳字面量的区别
	年部分的取值范围:前者年的部分是1000---9999,后者年的部分是1970---2037
	时间戳字面量在存取时会自动根据时区进行转换:在保存到表中时,自动按UTC(0时区)做转换;当从表中查询时,自动按客户端会话的时区做转换
#注:mysql会和系统是相同时区
	查看当前客户端的时区设置
root@test mysql>select @@time_zone;						#注:当前的时间变量
+-------------+
| @@time_zone |
+-------------+
| SYSTEM      |
+-------------+
1 row in set (0.00 sec)
root@test mysql>select @@SYSTEM_time_zone;				#注:查看时区;系统的时间变量
+--------------------+
| @@SYSTEM_time_zone |
+--------------------+
| CST                |
+--------------------+
1 row in set (0.00 sec)
#注:指定时间戳类型
root@test mysql>CREATE  TABLE  user_login(login_time  TIMESTAMP,username varchar(20));
root@test mysql>insert into user_login values(now(),'cali');	#注:now()函数
root@test mysql>select * from user_login;
+---------------------+----------+
| login_time          | username |
+---------------------+----------+
| 2021-03-13 23:34:25 | cali     |
+---------------------+----------+
1 row in set (0.01 sec)
将客户端的时区修改为东10区(澳大利亚悉尼):
SET  time_zone='+10:00';
SELECT  @@time_zone;
SELECT  *  FROM  user_login;

DISTINCT

重复的行
使用DISTINCT关键字可以去掉结果集中的重复行 (去重)

	SELECT  town  FROM players;
	SELECT  DISTINCT town  FROM players;

	SELECT  street, town 
  	FROM  players;
	SELECT  DISTINCT street, town
  	FROM  players;
DISTINCT	去重:去除重复的行
写SQL语句
	关键字是大小写不敏感的
	数据库名、表名、表别名在Linux下是大小写敏感的(可以配置成不敏感的)
	列名、列别名是大小写不敏感的
1:查询所有的罚款信息,要求显示所有的列
表:罚款表
字段:*
条件:

select * from PENALTIES;
select AMOUNT,PLAYERNO from PENALTIES;
select AMOUNT 金额,PLAYERNO 球员编号 from PENALTIES;		#注:alias 列起别名
select AMOUNT as 金额,PLAYERNO as 球员编号 from PENALTIES;

使用算术运算符

3:查询所有的罚款信息,要求显示球员编号、罚款金额以及罚款金额加上300之后的结果
	select  playerno,amount ,amount + 300
    	from penalties;
使用小括号可以改变运算的优先级
 	SELECT  playerno, amount , 12*amount + 100
    	FROM penalties;
 	SELECT  playerno, amount , 12*(amount + 100)
    	FROM penalties;
NULLNULL值,又叫做空值,它表示“未知的”意思。一个列具有NULL值,表示该值是未知的、不确定的NULL值不等于数字0或者空字符串’’,甚至 null  != NULL

 SELECT  playerno, name, leagueno
     FROM  players;
 SELECT  playerno, name, leagueno
     FROM  players WHERE leagueno is not null;
如果算术表达式中包含null值,则整个表达式的计算结果就为null

root@test mysql>select 100*12*NULL;
+-------------+
| 100*12*NULL |
+-------------+
|        NULL |
+-------------+
列别名
列别名(alias):给列取的另一个名字
列别名直接跟在列名后面,中间可以加一个AS关键字,也可以不加
列别名中如果包含空格或特殊字符,必须使用双引号或单引号括起来。建议使用双引号

 SELECT last_name  'full-Name', 12*salary  "Annual Salary"
     FROM  employees;
 SELECT  last_name  姓名, commission_pct  佣金
     FROM  employees;

字符串连接

concat_ws()和concat()的区别?
	两个都是字符串拼接函数,只是concat_ws可以指定分隔符
要把两个字符串值首尾相连的连接起来,如果@@sql_mode中没有设置“PIPES_AS_CONCAT”,就不能使用oracle中的||操作符,只能使用concat函数或者concat_ws函数
函数的参数就是需要连接的字符串值。可以有n个参数

例11SELECT  concat(last_name, job_id)  "Employees"
    FROM employees;

注意:concat函数在连接字符串的时候,只要其中一个是NULL,那么将返回NULL12select  concat('11','22',null);
root@test mysql>SELECT NAME,SEX FROM PLAYERS;
root@test mysql>SELECT CONCAT(NAME,SEX) FROM PLAYERS;
root@test mysql>SELECT CONCAT(NAME,' ',SEX) FROM PLAYERS;
root@test mysql>SELECT CONCAT(NAME,'#',SEX) FROM PLAYERS;
concat_ws()函数, 表示concat with separator,即有分隔符的字符串连接
例13:连接后以逗号分隔
   SELECT  concat_ws(',' , '11','22','33'); 

root@test mysql>SELECT CONCAT_ws('#',NAME,SEX,town) information FROM PLAYERS;

DESC

查看表结构
1 .desc
	DESC PLAYERS;
2 .SHOW CREATE TABLE PLAYERS;

WHERE

使用WHERE子句
如果想限制查询返回的行,需要使用WHERE子句
	WHERE条件又叫做过滤条件,它从FROM子句的中间结果中去掉所有条件conditions不为TRUE(而为FALSE或者NULL)的行
	WHERE子句跟在FROM子句后面
	不能在WHERE子句中使用列别名
1:查询住在Stratford(斯特拉福德,威廉-莎士比亚的出生地)的球员的编号
select 
表:球员
字段:编号
条件:住在Stratford  town

select PLAYERNO from PLAYERS,town WHERE town = "Stratford";

WHERE中出现的字符串和日期字面量必须使用引号括起来
这里,字符串字面量写成大写或小写结果都一样,即不区分大小写进行查询。这和ORACLE不同,ORACLE中WHERE条件中的字面量是区分大小写的

字符集和校对规则

root@test mysql>show character set;			#注:查看mysql里的字符集
collation		校对规则 --> 排序规则
A a    B b

每个字符集有一个默认校对规则。例如,utf8默认校对规则是utf8_general_ci

*_bin:  binary case sensitive collation,区分大小写 ,直接比较字符的编码
*_cs:    case sensitive collation,区分大小写,相同字符靠近排列 
*_ci:    case insensitive collation,不区分大小写 
#注:指定字符集
root@test mysql>create table guozy1(id int) default charset=utf8;
root@test mysql>show create table guozy1;

编译安装MySQL时,指定字符集 或者 建库的时候指定字符集
查看数据库支持的所有字符集
	show character set;
查看数据库支持的所有校对规则
	show collation;
查看当前字符集和校对规则设置
	show variables like 'collation_%';
	show variables like 'character_set_%';

比较运算符

2:得到联盟会员号码为7060的球员的编号
SELECT  playerno
  FROM  players
  WHERE  leagueno='7060';
3: 得到没有联盟会员号码的球员的编号
SELECT  playerno,leagueno
  FROM  players
  WHERE  leagueno  <=>  NULL;
或者:
SELECT  playerno,leagueno
  FROM  players
  WHERE  leagueno  IS NULL;
4:找出获胜局数等于2并且输掉局数等于3的比赛的编号
表:比赛表
字段:编号
条件:获胜局数等于2并且输掉局数等于3

select matchno from MATCHES 
WHERE LOST = 3 AND WON = 2;

SELECT  matchno
  FROM  matches
  WHERE (won,lost) = (2,3); 

MySQL在内部把条件重写为(won=2) and (lost=3)
5:找出19621964年之间出生的球员的编号、出生日期
表:球员
字段:编号、出生日期
条件:19621964年之间出生

SELECT playerno,birth_date
  FROM players
WHERE birth_date BETWEEN1962-01-01AND1964-01-01;

SELECT playerno,birth_date
  FROM players
WHERE birth_date >=1962-1-1and birth_date <=1964-1-1;

#注:BETWEEN …AND…	包含了等于

IN操作符
	测试一个列值是否在一个值列表中。值列表中可以是字面量、列或 标量子查询
6:得到那些出生在196219631970的球员的编号、出生年份
SELECT  playerno,year(birth_date)
  FROM  players
  WHERE  year(birth_date) IN (1962,1963,1970);

#注:year()函数  可以取出年份
	内置函数

#注:内置函数
	year()		取出年份
	month()		取出月份
	day()		取出天份
表:球员
字段:编号、出生年份
条件:出生在196219631970
select playerno,year(birth_date) from PLAYERS WHERE YEAR(BIRTH_DAYE) IN (1962,1963,1970);
6:得到那些和baker或者Hope同年的球员的编号、姓名
select playerno,name from PLAYERS where year(birth_date) in (select year(birth_date) from PLAYERS where name = ‘baker’ or name = ‘Hope’);

select playerno,name from PLAYERS where year(birth_date) in (select year(birth_date) from PLAYERS where name in (‘baker’,’Hope’));
7:对于那些有两局获胜或者两局输掉的所有比赛,得到比赛编号、获胜的局数和输掉的局数
SELECT  matchno,won,lost
  FROM  matches
  WHERE  2  IN  (won, lost);
在mysql内部,in转换成or操作,not  in转换成and操作
IN也可以进行成对比较
例8:对于那些比分为3132的所有比赛,得到比赛编号、获胜局数、输掉局数
SELECT  matchno, won, lost
  FROM  matches
  WHERE  (won, lost)  IN  ((3,1),(3,2));

LIKE操作符

实现模式匹配查询或者模糊查询
	%:表示0个或者任意多个字符
	_:只表示一个任意字符
9:找出名字以大写字母B开头的球员的名字和编号
	SELECT  name, playerno
  	FROM  players
	WHERE  NAME  LIKE  'B%';
10:得到名字以小写字母r结尾的球员的名字和编号
	SELECT  name, playerno
  	FROM  players
	WHERE  name  LIKE  '%r';
11:得到名字的第二个字母为e的球员的名字和编号
SELECT  name, playerno
  FROM  players
WHERE  name LIKE  '_e%';
root@(none) mysql>show variables;
root@(none) mysql>show variables like "%innodb%";				#注:包含innodb的变量
root@(none) mysql>show variables like "time_zone";				#注:精确匹配

REGEXP操作符

^			代表以什么开头
$			代表以什么结尾
[1234abcd]	匹配其中的任意一个
[^123]		不是123的任意一个字符
[0-9]		取其一
[a-z]
[A-Z]
[0-z]
[0-Z]
men3		n出现3次
cali3,6	i出现3-6次
liu5,		u出现5次以上
13:得到名字以ba开头的球员的编号和名字
SELECT  playerno, name
  FROM  players
  WHERE  name REGEXP  '^ba';
14:得到名字包含了字母a、b或c的球员的编号和名字
SELECT  playerno, name
  FROM  players
  WHERE  name REGEXP '[abc]';
15:对于名字中有字母m、e、n中的一个,并且连续出现2次的球员的编号和名字
SELECT  playerno,name
  FROM  players
  WHERE  name REGEXP '[men][men]';

逻辑操作符

使用逻辑操作符

有4个:and、 or、 not、 xor,用于在WHERE条件中把多个条件组合起来
	逻辑与、逻辑或、逻辑非、逻辑异或
AND操作符
例16:得到1970年之后出生的每个男球员的编号、名字、性别和出生日期
SELECT  playerno, name, sex, birth_date
  FROM  players
 WHERE  birth_date  >  '1970-12-31'
      AND  sex = 'M';
OR操作符
例17:得到住在Plymouth或者Eltham的球员的编号、姓名和居住城市
SELECT  playerno, name, town
  FROM  players
WHERE  town =  'Plymouth'
        OR  town = 'Eltham'; 
NOT操作符
	用在一个条件的前面。经常和其它操作符一起使用。例如:not innot betweennot likeis not null18:得到那些未住在Stratford的球员的编号、姓名
SELECT  playerno, name
  FROM  players
WHERE   NOT  (town = 'Stratford');19:查找罚款金额不是25美元或者50美元的球员的编号
SELECT  playerno
  FROM  penalties
WHERE  amount  NOT IN (25,50);
XOR操作符
例21:得到那些住在Stratford或者出生于1963年的球员的编号、姓名、出生日期,但是不包括那些住在Stratford并且出生于1963年的球员
SELECT  playerno, name, birth_date
  FROM  players
WHERE  (town = 'Stratford' )  
      XOR  (year(birth_date)='1963');

以上是关于08_MySQL笔记-锁-常量-DISTINCT-DESC-WHERE的主要内容,如果未能解决你的问题,请参考以下文章

学习笔记MySQL数据库高级版 - 索引优化慢查询锁机制等

MySQL所谓的乐观锁与悲观锁 -- 2019-08-08 20:39:47

(转)Mysql存储引擎__笔记

MySQL 查询优化 - distinct、order by 和 limit

MYSQL性能调优08_事务及其ACID属性脏读不可重复读幻读隔离级别行锁表锁读锁写锁间隙锁临键锁

mysql基础学习笔记