作者:matrix
发布时间:2021-12-28
分类:mysql PHP
结论
不要用float、double类型存储浮点数。改用decimal字段类型
过程
之前是知道浮点数最好不要用float类型做存储,手上遇到老项目使用就正好是float字段存储的体重数据,比如51.6
这种。
普通的查询没问题,个别数据就出现查询为空的问题。后来发现都是浮点类型数据,排查框架的sql日志到PDO的参数绑定找遍了都没找到根源。还以为是PDO扩展的data_type出错,因为内部sql执行时浮点数的参数绑定是使用PDO::PARAM_STR
。
$this->PDOStatement->bindValue(':ThinkBind_1_', 51.6, PDO::PARAM_STR)
虽然字段设置了精度float(10,2)
,但是依然有查询为空出现。这就是float精度导致的问题。
吐槽
TP5.1 sql日志输出不准确,和实际执行的不一致!
sql输出日志为where wi=51.6
,实际上执行是where wi="51.6"
,这也增加了排查的难度。
办法
- 浮点数查询使用like
- 使用函数比如
oncat(wi)=51.6
,或者format(wi,2) = format(51.6 ,2)
- 使用
decimal
字段类型
参考:
https://www.cnblogs.com/powerwu/articles/8465031.html
https://blog.csdn.net/luccs624061082/article/details/84286253
作者:matrix
发布时间:2021-03-31
分类:mysql
平时习惯使用mysql客户端工具直接导出表数据,这突然需要导出指定前缀的表反而变得麻烦,因为表非常多但又不想全部选择。
e.g. 导出dict_
开头的数据表
查询符合条件的表名
select table_name from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = 'heal' and table_name like 'dict_%';
执行导出命令
mysqldump --column-statistics=0 -h 127.0.0.1 -P3306 -pPASSWORD -t heal -uroot --tables dict_union dict_tag > ~/db_script.sql
-P端口号
-p密码
--tables
指定多个数据表
报错 mysqldump: Couldn't execute
mysqldump: Couldn't execute 'SELECT COLUMN_NAME, JSON_EXTRACT(HISTOGRAM, '$."number-of-buckets-specified"') FROM information_schema.COLUMN_STATISTICS WHERE SCHEMA_NAME = 'heal' AND TABLE_NAME = 'dict_union';': Unknown table 'COLUMN_STATISTICS' in information_schema
需要添加参数--column-statistics=0
参考:
https://www.cnblogs.com/commissar-Xia/p/10302336.html
https://researchlab.github.io/2017/02/22/mysql-import-export-summary/
作者:matrix
发布时间:2020-08-31
分类:Python 零零星星
第一次drop超过GB的数据表,没想到竟然会执行的这么慢。尝试过TRUNCATE
和DROP
都不满意。
后来就直接找到数据库储存的文件来删除,这样比起使用sql语句操作会快得多,但也是危险操作,无法找回。
删除操作脚本
运行环境 python3.7,依赖pymysql
,根据自身情况配置变量mysql_data_dir,db_config,table_names,condition_save
fast_drop_table.py
#codeing=utf-8
"""
快速清空超大数据表 保留想要数据
"""
import pymysql
import os
mysql_data_dir = '/mnt/mysql_data/db_name/' #数据库文件所在路径
# 数据库连接配置
db_config = {'host': '127.0.0.1', 'port': 3306, 'user': 'user', 'password': 'password', 'db': 'db_name', 'charset': 'utf8'}
# 需要清空操作的数据表
table_names = [
"com_hhtjim_badata_trades_eos_this_quarter",
"com_hhtjim_badata_trades_eth_this_quarter",
]
# 数据表保留的查询条件
condition_save = "timestamp > '2020-02-20T00:00:00Z'"
# condition_save = False# 不保留
class Db:
'''
简单数据库连接操作类
'''
def __init__(self,**kwargs):
self.connection = pymysql.connect(**kwargs)
self.cursor = self.connection.cursor()
if __name__ == "__main__":
mysql = Db(**db_config)
for table_name in table_names:
os.link('{}{}.frm'.format(mysql_data_dir,table_name), '{}{}.frm.h'.format(mysql_data_dir,table_name))
os.link('{}{}.ibd'.format(mysql_data_dir,table_name), '{}{}.ibd.h'.format(mysql_data_dir,table_name))
mysql.cursor.execute('CREATE TABLE {0}_back like {0}'.format(table_name))
mysql.connection.commit()
if condition_save:
mysql.cursor.execute("INSERT INTO {0}_back SELECT * FROM {0} WHERE {1} ;".format(table_name,condition_save))
mysql.connection.commit()
mysql.cursor.execute("drop table {}".format(table_name))
mysql.connection.commit()
mysql.cursor.execute("alter table {0}_back rename to {0};".format(table_name))
mysql.connection.commit()
os.unlink('{}{}.frm.h'.format(mysql_data_dir,table_name))
os.unlink('{}{}.ibd.h'.format(mysql_data_dir,table_name))
print('succeed: {}'.format(table_name))
具体步骤
### 找到frm,ibd文件
根据数据库存储路径找到需要删除的表名的frm,ibd文件。
### 建立硬连接
$ ln mytable.ibd mytable.ibd.h
$ ln mytable.frm mytable.frm.h
### 备份表结构
CREATE TABLE mytable_back like mytable;
### 备份想要保留的数据
INSERT INTO mytable_back SELECT * FROM mytable WHERE timestamp > '2020-02-27T00:00:00Z' ;
### 删除旧表
drop table mytable;
### 修改备份表名字
alter table mytable_back rename to mytable;
### 删除硬连接
$ rm -f mytable.frm.h mytable.ibd.h
参考:
https://blog.csdn.net/weixin_34034261/article/details/86250223
作者:matrix
发布时间:2020-03-31
分类:mysql
需要每天定时删除旧数据 避免占用大量磁盘空间
用到mysql事件调度器event_scheduler
SHOW VARIABLES LIKE 'event_scheduler'; # 查看开关
SET GLOBAL event_scheduler = ON; #打开事件调度器
#查看事件
SHOW EVENTS;# 其中 EVENT_DEFINITION字段为事件执行的sql语句
select EVENT_NAME,LAST_EXECUTED from information_schema.EVENTS;
DROP EVENT [IF EXISTS] event_name;#删除事件
定时删除旧数据
#每天定时清理 只保留最近30天数据schedule_del_depth5_eos_quarter表
CREATE EVENT IF NOT EXISTS schedule_del_depth5_eos_quarter
ON SCHEDULE EVERY 1 DAY
STARTS concat(CURRENT_DATE,' 00:00:00')
DO
delete from schedule_del_depth5_eos_quarter where timestamp < DATE_FORMAT( date_sub(curdate(),interval 30 day) ,'%Y-%m-%d');
参考:
https://www.cnblogs.com/geaozhang/p/6821692.html
https://blog.csdn.net/beyondlpf/article/details/39672599
https://blog.csdn.net/small____fish/article/details/7621160
https://blog.csdn.net/qq_33083551/article/details/88789311
作者:matrix
发布时间:2019-03-12
分类:Python
虚拟机ubuntu中自带了Python2,但是想要使用python3需要单独安装。使用add-apt-repository
来添加ppa源安装提示command not found
,之后进行安装操作sudo apt-get install software-properties-common
,错误继续:
$ sudo apt-get install software-properties-common
Reading package lists... Done
Building dependency tree... 50%
Building dependency tree
Reading state information... Done
You might want to run 'apt-get -f install' to correct these:
The following packages have unmet dependencies:
libmysql++-dev : Depends: libmysqlclient-dev but it is not going to be installed
software-properties-common : Depends: python3:any (>= 3.3.2-2~)
Depends: python3 but it is not going to be installed
Depends: python3-gi but it is not going to be installed
Depends: gir1.2-glib-2.0 but it is not going to be installed
Depends: python-apt-common (>= 0.9) but it is not going to be installed
Depends: python3-dbus but it is not going to be installed
Depends: python3-software-properties (= 0.96.20.8) but it is not going to be installed
E: Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).
继续apt-get update & upgrade & 更换国内源,后面使用apt-get install Python3也是相同错误,无济于事。
错误跟踪到libmysql++-dev依赖问题,遂重新安装sudo apt-get install libmysqlclient-dev
:
$ sudo apt-get install libmysqlclient-dev
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
libmysqlclient-dev
0 upgraded, 1 newly installed, 0 to remove and 163 not upgraded.
4 not fully installed or removed.
Need to get 0 B/1,167 kB of archives.
After this operation, 7,040 kB of additional disk space will be used.
debconf: delaying package configuration, since apt-utils is not installed
(Reading database ... 51891 files and directories currently installed.)
Preparing to unpack .../libmysqlclient-dev_5.7.25-0ubuntu0.16.04.2_amd64.deb ...
Unpacking libmysqlclient-dev (5.7.25-0ubuntu0.16.04.2) ...
dpkg: error processing archive /var/cache/apt/archives/libmysqlclient-dev_5.7.25-0ubuntu0.16.04.2_amd64.deb (--unpack):
unable to install new version of '/usr/include/mysql/mysql/plugin_ftparser.h': No such file or directory
Errors were encountered while processing:
/var/cache/apt/archives/libmysqlclient-dev_5.7.25-0ubuntu0.16.04.2_amd64.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)
尝试手动安装deb:sudo dpkg -i /var/cache/apt/archives/libmysqlclient-dev_5.7.25-0ubuntu0.16.04.2_amd64.deb
失败:
unable to install new version of '/usr/include/mysql/mysql/plugin_ftparser.h': No such file or directory
根源问题
/usr/include/mysql/mysql/plugin_ftparser.h
不存在
开始手动查找
$ sudo find / | grep plugin_ftparser.h
该文件只存在与/usr/local/mysql/include/
目录中,ls /usr/include/mysql -al
查看列表就会发现mysql
的软链接出现问题导致的。
解决
重新生成mysql include软连接
$ ln -s /usr/local/mysql/include /usr/include/mysql/mysql #重新生成软连接
此虚拟机中的mysql是之前安装LNMP搭建PHP环境而创建的,很有可能和这个有关系。
参考:
https://askubuntu.com/questions/629448/file-mysql-h-cant-be-found
https://askubuntu.com/questions/773079/fixing-broken-packages-in-ubuntu-repost
PEACE~
作者:matrix
发布时间:2018-10-29
分类:零零星星
SOAR -- sql Optimizer And Rewriter 由小米运维 DBA 团队开发的sql 智能优化与改写工具20181021宣布开源。
github:https://github.com/xiaomi/soar
安装说明:https://github.com/XiaoMi/soar/blob/master/doc/install.md
测试环境:ubuntu 16.04
安装GO
apt-get安装失败改用
源码下载:https://GOlang.GOogle.cn/dl/
配置环境变量
解压:
> sudo tar -C /usr/local -xzf go1.11.1.linux-amd64.tar.gz
全局用户的环境变量:
> sudo vi /etc/profile
末尾添加:
export PATH=$PATH:/usr/local/go/bin
go版本查看:
> go version
source更新环境变量:
source /etc/profile
还需要配置GOPATH环境变量:表示go的工作目录 USER_NAME 为用户名
export GOPATH="/home/USER_NAME/go"
安装soar
> go get -d github.com/XiaoMi/soar
> cd ${GOPATH}/src/github.com/XiaoMi/soar && make
若安装顺利,最终会显示success
。否则 build error
我前几次安装都失败
go build github.com/pingcap/tidb/parser: /usr/local/go/pkg/tool/linux_amd64/compile: signal: killed
Makefile:69: recipe for target 'build' failed
之后google找到帖子 有人说是vps内存太低导致的,遂重启了下Ubuntu 重新make
。bingo~
安装成功之后会发现~/go/src/github.com/XiaoMi/soar
多出一个 soar
文件。
执行测试:
> cd ~/go/src/github.com/XiaoMi/soar
> echo 'select * from film' | ./soar
使用soar
常用命令:https://github.com/XiaoMi/soar/blob/master/doc/cheatsheet.md
打印所有的启发式规则
$ soar -list-heuristic-rules
打印支持的报告格式
$ soar -list-report-types
以指定格式输出报告
$ soar -report-type json
语法检查工具
$ echo "select * from tb" | soar -only-syntax-check
$ echo $?
0
$ echo "select * fromtb" | soar -only-syntax-check
At SQL 0 : syntax error at position 16 near 'fromtb'
$ echo $?
1
慢日志进行分析示例
$ pt-query-digest slow.log > slow.log.digest
# parse pt-query-digest's output which example script
$ python2.7 doc/example/digest_pt.py slow.log.digest > slow.md
SQL指纹
$ echo "select * from film where col='abc'" | soar -report-type=fingerprint
输出
select * from film where col=?
将UPDATE/DELETE/INSERT语法转为SELECT
$ echo "update film set title = 'abc'" | soar -rewrite-rules dml2select,delimiter -report-type rewrite
输出
select * from film;
合并多条ALTER语句
$ echo "alter table tb add column a int; alter table tb add column b int;" | soar -report-type rewrite -rewrite-rules mergealter
输出
ALTER TABLE `tb` add column a int, add column b int ;
SQL美化
$ echo "select * from tbl where col = 'val'" | ./soar -report-type=pretty
输出
SELECT
*
FROM
tbl
WHERE
col = 'val';
EXPLAIN信息分析报告
$ soar -report-type explain-digest << EOF
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | film | ALL | NULL | NULL | NULL | NULL | 1131 | |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
EOF
## Explain信息
| id | select\_type | table | partitions | type | possible_keys | key | key\_len | ref | rows | filtered | scalability | Extra |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | *film* | NULL | ALL | NULL | NULL | NULL | NULL | 0 | 0.00% | ☠️ **O(n)** | |
### Explain信息解读
#### SelectType信息解读
* **SIMPLE**: 简单SELECT(不使用UNION或子查询等).
#### Type信息解读
* ☠️ **ALL**: 最坏的情况, 从头到尾全表扫描.
markdown转HTML
通过指定-report-css, -report-javascript, -markdown-extensions, -markdown-html-flags这些参数,你还可以控制HTML的显示格式。
$ cat test.md | soar -report-type md2html > test.html
PEACE~
参考:
https://github.com/beego/wetalk/issues/32
https://www.oschina.net/news/101034/xiaomi-opensource-soar
https://juejin.im/entry/5bbf21fde51d450e61605d99
作者:matrix
发布时间:2018-05-03
分类:零零星星
业务要求按照type,city分组,然后各取前面的100条数据输出,网上找到了类似的需求直接sql语句就可以解决。
测试表结构
CREATE TABLE `esc_catch` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`city` varchar(20) NOT NULL DEFAULT '' COMMENT '城市',
`price` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '报价',
`type` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '1,2',
`add_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '添加时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
解决办法
set @row=0;set @city=''; set @type='';
select a.city,a.price,a.type ,from_unixtime(a.add_time,'%Y-%m-%d %H:%i:%s') as add_time from esc_catch as a
inner join (
SELECT id,add_time, case when (@city = city and @type= type) then @row:=@row+1 else @row:=1 end as rownum, @city:=city as city , @type:=type as type FROM esc_catch order by type,city,add_time desc
) as b on b.id = a.id
where b.rownum>=100 order by b.type,b.city ;
说明:
头部事先声明变量
row
用于统计指定分组下出现的次数,
city
和type
是分组条件
核心在于inner join
的的临时表操作,其中使用变量操作追加rownum
字段
如果变量city
,type
值等同于临时表的同名字段则该行数据排序下标row++,否则为1
@city:=city as city , @type:=type as type 表示给每行数据的字段值赋给变量
之后在inner join内联表 之后使用自定义的rownum
字段b.rownum<=100
进行数量条件的限制即可,最后order by
操作便于查看数据
参考:
https://blog.csdn.net/ylqmf/article/details/39005949
https://blog.csdn.net/woshihaiyong168/article/details/78803655
https://zhidao.baidu.com/question/618263527798895012.html
PEACE~
作者:matrix
发布时间:2017-02-11
分类:零零星星
重启系统发现mysql启动失败。
环境为 ubuntu Lnmp
Starting MySQL
. * The server quit without updating PID file (/var/run/mysqld/mysqld.pid).
/var/run/mysqld/
目录中没有pid文件
找到网上说的文件权限、磁盘已满,这些都不符合情况。
解决
删除文件my.cnf
> rm /etc/mysql/my.cnf
启动mysql
lnmp mysql start
最后启动成功就ok
peace
参考:
http://blog.ich8.com/post/5635
https://bbs.vpser.net/viewthread.php?tid=13217