用 pt-table-checksum 时,会不会影响业务性能?
实验
实验开始前,给大家分享一个小经验:任何性能评估,不要相信别人的评测结果,要在自己的环境上测试,并(大概)知晓原理。
我们先建一对主从:
然后用 mysqlslap跑一个持续的压力:
开另外一个会话,将 master 上的 general log 打开:
然后通过 pt-table-checksum 进行一次比较:
查看 master 的 general log,由于 mysqlslap 的影响,general log 中有很多内容,我们找到与 pt-table-checksum 相关的线程:
将该线程的 *** 作单独列出来:
*** 作比较多,我们一点一点来说明:
这里工具调小了 innodb 锁等待时间。使得之后的 *** 作,只要在 innodb 上稍微有锁等待,就会马上放弃 *** 作,对业务影响很小。
另外工具调小了 wait_timeout 时间,倒是没有特别的作用。
工具将隔离级别调整为了 RR 级别,事务的维护代价会比 RC 要高,不过后面我们会看到工具使用的每个事务都很小,加上之前提到 innodb 锁等待时间调到很小,对线上业务产生的成本比较小。
RR 级别是数据对比的基本要求。
工具通过一系列 *** 作,了解表的概况。工具是一个数据块一个数据块进行校验,这里获取了第一个数据块的下边界。
接下来工具获取了下一个数据块的下边界,每个 SQL前都会 EXPLAIN 一下,看一下执行成本,非常小心翼翼。
之后工具获取了一个数据块的 checksum,这个数据块不大,如果跟业务流量有冲突,会马上出发 innodb 的锁超时,立刻退让。
以上是 pt-table-checksum 的一些设计,可以看到这几处都是精心维护了业务流量不受影响。
工具还设计了其他的一些机制保障业务流量,比如参数 --max-load 和 --pause-file 等,还有精心设计的数据块划分方法,索引选择方法等。大家根据自己的情况配合使用即可达到很好的效果。
总结
本期我们介绍了简单分析 pt-table-checksum 是否会影响业务流量,坊间会流传工具的各种参数建议或者不建议使用,算命的情况比较多,大家都可以用简单的实验来分析其中机制。
还是那个观点,性能测试不能相信道听途说,得通过实验去分析。
企业管理器-->右键你的实例(就是那个有绿色图标的)-->属性-->安全-->改为sql与window混合
连接字符串中添加:
integrated security = SSPI
即可,不需要再添加UID和password的子串。
Integrated
Security=True;表示在连接数据库进行身份验证时用windows集成的身份验证模式,TRUE可以改成SSPI表示同一个意思,如果为False的话,就会用Userid
和PW的模式进行登陆,也就是说当Integrated
Security=true;时UserID和Pw是不起作用的,只有当其设置为False时数据库才会用UserId和Pw的方式进行登录,可以设成Integrated
Security={true,False,yes,No,SSPi}这几个参数,其中TRUE=yes=SSpI。Pooling=False表示是否使用连接池,False表示不使用连接池,连接池就是有一些与数据库的连接放在里面,建立新的连接时系统会先看里面有没有一样的连接,有就不用新建了。
using System
using System.Collections.Generic
using System.Text
using System.Data
using System.Data.SqlClient
namespace SQL_work
{
class DataConn
{
public static SqlConnection My_con //定义一个SqlConnection类型的公共变量My_con,用于判断数据库是否连接成功
public static string M_str_sqlcon = @"Data Source=计算机名/SQLEXPRESSInitial Catalog=db_work3Integrated Security=TruePooling=False"
#region 建立数据库连接
/// <summary>
/// 建立数据库连接.
/// </summary>
/// <returns>返回SqlConnection对象</returns>
public static SqlConnection getcon()
{
My_con = new SqlConnection(M_str_sqlcon) //用SqlConnection对象与指定的数据库相连接
My_con.Open() //打开数据库连接
return My_con //返回SqlConnection对象的信息
}
#endregion
#region 测试数据库是否赋加
/// <summary>
/// 测试数据库是否赋加
/// </summary>
public void con_open()
{
getcon()
//con_close()
}
#endregion
#region 关闭数据库连接
/// <summary>
/// 关闭于数据库的连接.
/// </summary>
public void con_close()
{
if (My_con.State == ConnectionState.Open) //判断是否打开与数据库的连接
{
My_con.Close() //关闭数据库的连接
My_con.Dispose() //释放My_con变量的所有空间
}
}
#endregion
#region 读取指定表中的信息
/// <summary>
/// 读取指定表中的信息.
/// </summary>
/// <param name="SQLstr">SQL语句</param>
/// <returns>返回bool型</returns>
public SqlDataReader getcom(string SQLstr)
{
getcon() //打开与数据库的连接
SqlCommand My_com = My_con.CreateCommand()//创建一个SqlCommand对象,用于执行SQL语句
My_com.CommandText = SQLstr //获取指定的SQL语句
SqlDataReader My_read = My_com.ExecuteReader()//执行SQL语名句,生成一个SqlDataReader对象
return My_read
}
#endregion
#region 执行SqlCommand命令
/// <summary>
/// 执行SqlCommand
/// </summary>
/// <param name="M_str_sqlstr">SQL语句</param>
public void getsqlcom(string SQLstr)
{
getcon() //打开与数据库的连接
SqlCommand SQLcom = new SqlCommand(SQLstr, My_con)//创建一个SqlCommand对象,用于执行SQL语句
SQLcom.ExecuteNonQuery() //执行SQL语句
SQLcom.Dispose() //释放所有空间
con_close() //调用con_close()方法,关闭与数据库的连接
}
#endregion
#region 创建DataSet对象
/// <summary>
/// 创建一个DataSet对象
/// </summary>
/// <param name="M_str_sqlstr">SQL语句</param>
/// <param name="M_str_table">表名</param>
/// <returns>返回DataSet对象</returns>
public DataSet getDataSet(string SQLstr, string tableName)
{
getcon() //打开与数据库的连接
SqlDataAdapter SQLda = new SqlDataAdapter(SQLstr, My_con) //创建一个SqlDataAdapter对象,并获取指定数据表的信息
DataSet My_DataSet = new DataSet()//创建DataSet对象
SQLda.Fill(My_DataSet, tableName) //通过SqlDataAdapter对象的Fill()方法,将数据表信息添加到DataSet对象中
con_close() //关闭数据库的连接
return My_DataSet //返回DataSet对象的信息
//WritePrivateProfileString(string section, string key, string val, string filePath)
}
#endregion
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)