读一读

所谓的回表就是使用索引查出了数据中没有包含所有需要的列,就是不包含有非索引列,需要根据索引中的rowid回表出查出这个非索引列的值。

如果单纯的想要回去一两列的数组,可以创建组合索引,使索引包含所有列,然后就不需要回表了。注意维护索引的成本和使用情况。


在mysql命令行操作中,使用select语句导出需要的数据

select * into outfile '导出目录和文件' character set gbk from table;
#文件带后缀,支持多种格式的,例如xls
#目录的分隔符用/(window下),用\就会报下面错误

如果出现secure-file-priv相关的错误,表示你导出的目录是受限制的,需要导出到指定的目录

#查看相应的目录
show variables like '%secure%';
#看到secure-file-priv参数就是目标路径

将导出的目录修改为此目录即可,或则去配置文件修改此参数,重新启动mysql。


当你有一个主键表时,发现数据没有,就向里面插入数据。当多线程调用时,可能存在与两个或两个以上的线程判断到数据不存在,同时去插入数据。此时主键就会发生冲突,报错。

停止报错的方法就是在存储过程中开启事务去发现错误,然后制止这个行为。

BEGIN

	DECLARE iid INT DEFAULT 0;
	DECLARE t_error TINYINT DEFAULT 0;
	DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error = 1;

	SELECT UserID INTO iid from fish_game_status WHERE UserID = User_ID;

	IF iid = 0 THEN
		START TRANSACTION;##插入的时候开启事务,捕捉错误回滚
		INSERT INTO fish_game_status VALUES(User_ID,Statu);
		IF t_error = 1 THEN
		ROLLBACK;
		ELSE
		COMMIT;
		END IF;
	ELSE
	UPDATE fish_game_status SET GameStatus = Statu WHERE UserID = User_ID;
	END IF;

END

如果操作数据库的整体任何语句都很慢的话,可以先去查看慢查询日志,解决慢查询,分析慢查询可以用mysqldumpslow。一般来说,数据库查询慢应该就是慢查询导致的,慢查询占用了大量的服务器资源。如果是出现大量的慢查询,一些不会出现慢查询的sql也出现慢查询状态,可以优化一下环境,比如mysql的配置情况,增加缓存池的空间等。最后就是该考虑服务器硬盘IO、内存、网络、CUP等。纯属自己瞎比比!


这种情况可以直接Update后查看影响的行数来判断这条数据不存在,此时不存在,再去Insert,就免去了每次都要去Select一次判断数据的存在

DECLARE isCol TINYINT DEFAULT 0;

UPDATE fish_game_status SET GameStatus = Status WHERE UserID = User_ID;

SELECT ROW_COUNT() INTO isCol;

IF isCol = 0 THEN
INSERT INTO fish_game_status VALUES(User_ID,Status);
END IF;

注意,就是不要传相同状态过来,因为在Update的时候,数值相同时,影响的行数还是为0的,此时去插入数据,这就炸了,主键不能重复。所以应该在应用层实现判断且没改变一次只进行一次调用。


将慢查询的时间改为0s,那样所有的查询都会被记录起来,利用慢查询日志分析情况

mysqldumpslow是一个perl脚本,所以先下载ActivePerl,将bin目录注册到环境变量的Path中,重启

打开cmd,cd到mysql的bin目录(也就是mysqldumpslow.pl所在目录),调用命令

mysqldumpslow.pl -s t -t 10 D:\wamp64\logs\mysql_slow_query.log

-s表示排序方式,c、t、l、r分别是按照记录次数、时间、锁定时间、返回的记录数来排序,ac、at、al、ar,表示相应的平均

-t  top的意思,表示输出排行榜的前多少条。

最后接上你慢查询日志所在的地方,可以去ini文件查看所在位置。

更多的命令详情可以使用mysqldunpslow.pl --help查看


cmd下cd到mysql安装目录的bin目录下,调用

mysqld.exe --install MySql(服务名) --defaults-file="C:/数据目录/ProgramData/配置.ini"

show engine innodb status;

查看到LATEST DETECTED DEADLOCK部分

第一个事务是报死锁的,也就是描述正在等待的锁

第二个事务,第一个是拥有的锁,第二个等待的锁

详情看 我的Mysql死锁排查过程(案例分析)


两个存储过程 :

BEGIN
START TRANSACTION;
	if EXISTS (SELECT name from manydate where id=1) THEN
	SELECT SLEEP(3);##等待了3秒
	UPDATE manydate SET `name`="haha" WHERE id = 1;
	END IF;
COMMIT;
END
BEGIN
UPDATE manydate SET `name` = 'caca' WHERE id = 1;
END

先执行第一个,再执行第二个时,第二个就会报死锁。

首先执行第一个存储过程第一条Select时给予id=1添加了读锁,第二个存储过程Update需要给id=1添加写锁,但是因为前面加了读锁,等待。等待3秒,执行第一个存储过程的第二条Update,需要升级id=1读锁为写锁,但是前面有在排队请求的id=1的写锁,不能升级,等待,这样就死锁了。

第一个不用开启事务,不会发生死锁;不用IF EXISTS不会发生死锁,不知道为啥


新搭建好数据库mysql后,会建立一个root账户,而这个账户其实是'root'@'localhost',它只能允许本地链接,所以,当你在新的环境下用以前的存储过程definer='root'@'%'是不能调用的。因为'root'@'%'这个账号不存在。解决办法:

可以将存储过程导出后,替换调'%'为'localhost'

也可以修改root允许的host,mysql数据库的user表

update user set host=’%’ where user=’root’;