1. show processlist; 执行了时间,和观察因为某个进程导致之后的sql卡死的原因
2. SELECT trx_rows_locked,trx_mysql_thread_id FROM information_schema.innodb_trx;查看线程锁定的行数,和线程id
日历
-
近期文章
分类目录
friend
-
1. show processlist; 执行了时间,和观察因为某个进程导致之后的sql卡死的原因
2. SELECT trx_rows_locked,trx_mysql_thread_id FROM information_schema.innodb_trx;查看线程锁定的行数,和线程id
在单位接手一个项目,java开发的,做开发多年,解决过各种奇葩问题,没想到差点在java中文乱码这跌跟头。
java项目是在另一个部门移过来的线上的工程,使用maven构建开发。迁移过来后在本地打包,传到服务器上遇到提交中文到数据库中是乱码的问题。
1. 查看jdbc链接属性: jdbc:mysql://xxx.xxx.xxx.xxx:3306/xxx?useUnicode=true
确认使用参数testUnicode=true
2.确认数据库及表的编码(数据库也是从原部门直接dump过来的)
1)查看数据库编码:database encoding='utf-8 unicode';database collation='utf-8 unicode'
2)确认表、行编码,也是utf8;
3. 确认入参编码格式问题:
1)准备参数,通过浏览器拿到提交表单的curl命令
2)把curl的目标地址换成原部门测试环境,结果中文不会乱码,再把目标地址换回本地环境,结果中文乱码
4. 确认代码
1)跟原部门确认,代码是线上的,maven配置也是和线上环境一直的,线上一直没问题
5. 确认容器问题:
1)开始查看tomcat容器,tomcat用的是9(最新的)。在server.xml中设置 Connector 添加属性URIEncoding="UTF-8"(据说在tomcat8之后默认就是utf8了),结果不行
2)修改tomcat catalina.sh 文件,添加 JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8",结果不行
3)从原部门要来tomcat包(线上的),使用他们的tomcat,结果不行
4)原部门包分别执行5、6步骤,结果不行
5)yum下载tomcat重新部署,不行,分别执行5、6步骤,不行
到现在为止,已经过去了1天的时间,确定了入参、容器、代码还是没有解决问题(555555),从头开始。。。
1. 确认jdbc链接参数,发现useUnicode=true,但是没有写characterEncoding=utf-8,添加该参数,结果成功了,中文不再是乱码
已经找到了问题,是数据库链接的问题,为什么同样的数据库链接配置在原部门可用,在我们这就不行呢?继续~,去server上看my.cof,发现mysqld中没有设置默认编码,于是在[mysqld]中添加:character-set-server=utf8,重启mysql;从jdbc中拿掉characterEncoding参数,重新打包发布;结果ok。
1. 在部署mysql时,不要偷懒,一定要确认编码格式
2. 在代码中链接数据时,一定要显示指明编码情况,仅仅useUnicode=true是不够的(不能依赖数据库的配置)
3. 老生长谈的话,没有灵异的事件,只有没有发现的细节,慢慢来!!
4. 要有空杯心态,不要盲目的相信经验。解决不了的问题多余人交流。
go的交叉编译,比如 我用的mac,需要编译的可执行文件在linux上,如下
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOROOT=/usr/local/go GOPATH=/Users/wangchanghong/go go build -i -o ~/out/[文件名] 【编译目标】
#CGO_ENABLED 开启交叉编译
#GOOS 执行系统 linux
#GOARCH 运行目标版本 (可通过uname -a 获取)
比如说 提示 cannot find package "golang.org/x/net"
1. 尝试执行下面的命令
go get golang.org/x/net
如果不成功则继续
2.
mkdir -p $GOPATH/src/golang.org/x cd $GOPATH/src/golang.org/x git clone https://github.com/golang/net.git
golang 在 github 上建立了一个镜像库,如 https://github.com/golang/net 对应的是 https://golang.org/x/net,其他亦然。。
在上一篇文章中,介绍了如何在代码架构之初,为了以后的扩展方便做的考虑,那么在现实中大部分的情况不是如此,那么我们需要重构这块么?不一定,今天我们使用另一种方式来实现装饰器。
假设现在我们处在产品的第二个阶段,有下面第一阶段代码来实现需求
class User{
function loadData(){
$res = 'load ...' . PHP_EOL;
return $res;
}
}
还是同样的,怎么在不改变调用逻辑 和 User::loadData 的基础上来扩展呢。php给我们提供了一个方案:Trait
//首先,我们先实现一个trait
trait Count{
function loadData(){
$res = parent::loadData();
//count 的逻辑
return $res;
}
}
//接下来,把User类更名为UserBase
class UserBase {
function loadData(){
echo 'load ...' . PHP_EOL;
}
}
//紧接着,重新写一个User类来继承 UserBase(如果不这样做,代码使用者估计打死你的),并且使用 Count
class User extends UserBase{
use Count;
}
这样,我们就完成装饰器的功能,甚至能在不改变原来代码的情况下偷梁换柱做一些更加彻底的操作。
装饰器模式,也称修饰器模式。目的是给现有的对象增加或修改成新逻辑。说人话就是不改变对象的情况下,给对象的某个操作增加前置操作或者后置操作(当然也有可能改变操作的逻辑)。
举个栗子:
我们在操作数据库的时候会从数据库拉取数据,拉取数据的动作是 loadData,那么就可以针对loadData操作进行“装饰器”的封装。
1. 实现loadData接口,接口这里的目的是所有加载数据的地方都有一个统一的规范
interface loadDataInterface{
function loadData($where);
}
2. 实现上面的接口来封装model层
//db 是数据库的封装
class user extends db implements loadDataInterface{
function loadData($where){
//$this->db->query($where)
}
}
(一般情况下,做完上面两部,就完成了第一阶段的需求,如果后续阶段,需要在拉取用户数据后要执行特定的操作,比如说拉取了多少数据,怎么办呢?继续往下。。。)
3. 做一个装饰器
//装饰器封装了前置操作,和后置操作
abstract class loadDataDecorator implements loadDataInterface{
public $handle = null;
public $where = null;
function __construct(loadDataInterface $handle){
$this->handle = $handle;
}
abstract function loadBefore();
abstract function loadAfter();
function loadData($where){
$this->where = $where
$this->loadBefore();
$this->handle->loadData($this->where);
$this->loadAfter();
}
}
4. 实现拉取数据后记录数量的操作
class loadDataAfterCount extends loadDataDecorator{
//因为装饰器一并封装了前置操作,这里留空就行
function loadBefore(){
//do nothing
}
function loadAfter(){
//$this->db->queryCount($this->where)
}
}
5. 使用装饰器
$userModel = new loadDataAfterCount(new User) $userModel->loadData();
装饰器带来的思考:
有些同学可能注意到了,如果要实现拉取用户后记录多少数据被拉取,那么直接改 User::loadData 多方便,一句话的事,为啥要费老大的劲做真么多的操作呢?!其实封装的目的是代码(或者说逻辑)的重复可用,现在需要拉取用户后记录数据量,那么如果来去其他的数据后也记录呢?如果不仅仅是记录还有更多的更复杂的逻辑呢?这个时候,封装的好处就尤为明显了,只需在需要添加逻辑的位置“装饰”一下,这个世界就又那么美丽了~
在python3中,已经把str和bytes做了明显的分别,两者之间不能混用(纬度不一样),编程中直接声明的字符串使用的是unicode,在字符串存储或者传输时使用的是字节流(比特流),这个时候Python帮你做unicode转bytes。如果不需要Python帮你这么做。你可以直接使用字节的方式声明。
//str 转 bytes >>> s = '您好' >>> type(s) <class 'str'> >>> s '您好' >>> b = bytes(s, encoding='utf-8') >>> type(b) <class 'bytes'> >>> b b'\xe6\x82\xa8\xe5\xa5\xbd' //bytes 转 str >>> b1 = b'\xe6\x82\xa8\xe5\xa5\xbd' >>> b1 b'\xe6\x82\xa8\xe5\xa5\xbd' >>> s1 = str(b1, encoding='utf-8') >>> s1 '您好'
1. 安装软件
a.(https://dev.mysql.com/downloads/connector/python/)
brew cask install mysql-connector-python
b.(https://downloads.mysql.com/archives/utilities/)
brew cask install mysql-utilities
2. 比较两个数据库的方法(可以比较两个数据库表的差别)
mysqldiff --server1=user:pass@host:port:socket --server2=user:pass@host:port:socket db1:db2
3. 比较两个表的方法,以表1为比较源,以alter sql为输出,结果为表2执行什么语句可以变成表1
mysqldiff --server1=user:pass@host:port:socket --server2=user:pass@host:port:socket --changes-for=server2 --difftype=sql db1.table:db2.table
4.安装的mysql工具包括如下,有时间自己尝试:
mysqlauditadmin
mysqlauditgrep
mysqldbcompare
mysqldbcopy
mysqldbexport
mysqldbimport
mysqldiff
mysqldiskusage
mysqlfabric
mysqlfailover
mysqlfrm
mysqlindexcheck
mysqlmetagrep
mysqlprocgrep
mysqlreplicate
mysqlrpladmin
mysqlrplcheck
mysqlrplms
mysqlrplshow
mysqlrplsync
mysqlserverclone
mysqlserverinfo
mysqluc
mysqluserclone
再mysql执行事务中,禁止执行DDL 和 DCL语句,防止程序不可控!!
这种隐式的提交将把显示开启的事务也给提交。所以在事务中执行非DML的语句,将自动提交事务。之后的语句将在非事务中运行
对于DDL(create、alter、drop等开头的语句)和DCL(grant、revoke语句)事务,在执行每条语句之前和之后,MySQL会自动执行一条COMMIT语句,因此事务是自动开始和结束的。自动提交打开或者关闭对这些事务没有影响
对于DML事务,在自动提交关闭的情况下,事务的开始分为隐式开始和显式开始:
隐式开始:程序的第一条DML语句执行时或者在COMMIT或ROLLBACK语句之后执行第一条DML语句时,自动开始一个新的事务
显式开始:发出STRAT TRANSACTION语句。该语句会自动关闭自动提交,当事务结束后,autocommit变量恢复到原来的值