所谓的回表就是使用索引查出了数据中没有包含所有需要的列,就是不包含有非索引列,需要根据索引中的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部分
第一个事务是报死锁的,也就是描述正在等待的锁
第二个事务,第一个是拥有的锁,第二个等待的锁
两个存储过程 :
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’;