MySQL 主从时间字段相差1秒深度揭密

【UE5】三步搞定Pixel Streaming:从零搭建Windows像素流服务 本文详细介绍了如何在Windows平台上快速搭建UE5 Pixel Streaming像素流服务,从插件安装、项目打包到服务启动的全流程操作。通过实战案例和优化配置,帮助开发者实现零客户端配置、跨设备兼容的高性能3D应用流式传输,特别适合建筑可视化和实时协作场景。 阅读详情

1. 主从数据异常

         某实例一个datetime字段主从数据不一致,其它数据暂未发现异常。第一反应,有可能是人为修改,如果有用户有高权限帐号,是可能做到这事的,检查所有帐号权限排除了这种可能。难道有黑客入侵?神经一下绷紧,仔细排查各种系统状态,很快也排除了这种可能。同时分析业务类型,有问题的值都是从机都是比主少一秒,时间戳被改小一秒不能带来任何收益,被非法篡改的可能性基本排除。

2. 初步分析

         对比数据发现,从机比主机少一秒的数据经常出现,但从机主从复制状态一直正常,主机binlog中未发现有语句被跳过。对比master上binlog及slave上relaylog, relaylog和master上binlog完全一致,有问题的数据在master上binlog里就已经少一秒了,因此肯定从机状态是正常的,问题出在master上。         继续分析发现有问题的数据,发现在master上select出来和binlog中就是差一秒,很是诡异邪门。打开general_log,记录一段时间操作,抓到了大量的时间相差一秒的情况行的前后插入语句,观察发现general_log 和binlog中时间相同,但直接select出来的值多一秒,没有其它多余操作,完全排除非法篡改的情况。至此可以认定,异常数据在innodb引擎中存的数据和binlog中的数据是不一致的,在这里需要说明的是master上binlog格式是mixed,非row格式并不能完全保证binlog数据可靠。          继续分析geneal_log,有问题的行是都是通过Prepared Execute方式插入的,尝试联系前端人员复现问题未果后,自己想办法复现。分析问题数据有几个特点:

  1. Prepared Execute 方式插入
  2. 部分数据差一秒,非全部
  3. 有问题的数据在binlog中都是比innodb中的少一秒
  4. datetime字段未指定精度 由于前端大多是通过jdbc方式访问数据库,于是根据上面特征在本地构造jdbc用例操作库,绑定变量,构造prepare execute方式插入数据,当设置预编译模式(useServerPrepStmts=true)复现了bug,复现的java代码如下:
import java.sql.*;
import java.text.SimpleDateFormat;
public class insertData {
	public static void main(String[] args)
	{
		String driver = "com.mysql.jdbc.Driver";
		String url = "jdbc:mysql://127.0.0.1:3306/mydb?useServerPrepStmts=true";
		String user = "u1";
		String password = "123456";
		try 
		{
			Class.forName(driver);
			Connection conn = DriverManager.getConnection(url, user, password);
			if(!conn.isClosed())
				System.out.println("Succeeded connecting to the Database!");
			//String dateStr = "2018-09-25 14:36:45.666";  
			//SimpleDateFormat  form = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss.SSS");
			//java.util.Date date=form.parse(dateStr);
			//java.sql.Timestamp tmp= new java.sql.Timestamp(date.getTime());
			//System.out.println(tmp);
			long time = System.currentTimeMillis();
			Date date = new Date(time);
    	java.sql.Timestamp tmp= new java.sql.Timestamp(date.getTime());
  		System.out.println(tmp);  		
			//create table test(a datetime);
			PreparedStatement pstmt = conn.prepareStatement("insert into test values(?)");
			pstmt.setTimestamp(1, tmp);
			pstmt.execute();
			conn.close();
		}
		catch(ClassNotFoundException e) 
		{
			System.out.println("Sorry,can`t find the Driver!");
			e.printStackTrace();
		}
		catch(SQLException e) 
		{
			e.printStackTrace();
		} catch(Exception e) 
		{
			e.printStackTrace();
		}
	}
}

         用例很简单,取当前时间插入数据库,binlog中有不少时间值少一秒,如下图: 

 

第一个图是java插入数据并打印出原始时间数据,第二个图是数据库中binlog及直接查出的时间数据,显然秒以下精度大于0.5秒的两个时间出现了相差一秒的情况,至此可以初步认定该问题是由于精度引起,如果前端将秒以下精度清零再插入,不会有这问题。

3. 深度挖掘

一、前端参数简介

        到此问题似乎已经解决,前端精度清零即可,但是这只是临时方案,为什么精度不清零会有问题?根本原因是什么?精度问题前端页面和入库有不一致可以接受,但是在入库后binlog与innodb存的数据不一致,没有任何提示报错直接导致主从数据不一致,这是不能接受的,必须挖出根本原因,保证数据的可靠性。         当用其它方式操作库没有问题,用prepare不用预编译模式(useServerPrepStmts=false)也不会有问题,由此可见触发该问题的关键是是否使用预编译模式。

Jdbc对prepare的大致处理过程如下: useServerPrepStmts=true时Jdbc对prepare的处理 1) 创建PreparedStatement对象,向服务器发送COM_PREPARE命令,并传送带问号的sql. 服务器返回jdbc stmt->id等信息 2) 向服务器发送COM_EXECUTE命令,并只传送参数信息。 useServerPrepStmts=false时Jdbc对prepare的处理 1) 创建PreparedStatement对象,此时不会和服务器交互。 2) 根据参数和PreparedStatement对象拼接完整的SQL,向服务器发送QUERY命令 当使用预编译时prepare阶段发带问号语句到后端,执行时只发参数,相同语句后端只需要解析一次。非预编译时,prepare时与后端无交互,执行时拼接完整的SQL发到后端运行,即问号已经在前端被填充好值,每条语句都要解析一次。          预编译模式,执行时只发参数,引擎层把传过来的参数值处理落盘,而写入binlog的语句是把参数转换拼接而成。这里引擎层落盘数据和sql层转换拼接还原binlog语句是两个独立的过程,可以提出一个假设:如果sql层和引擎层对精度处理逻辑不一致,innodb引擎层对秒以下做四舍五入,而sql层直接舍弃秒以下精度,那么就可能造成这个问题。

二、binlog语句来处

        带着上面的假设分析源码,尝试从源码中继续寻找答案。先找binlog的语句来处,mysql中sql语句都保存在thd->query_string中,但这里的query_string中的参数是问号,它是在函数insert_params_with_log中拼接还原而成, 把时间值转成了字串符填入了sql中的问号,如下:

937	    if (query->replace(param->pos_in_query+length, 1, *res))
(gdb) bt
#0  insert_params_with_log (stmt=0x7f77e8c56280, null_array=0x7f77f7f6600a "", read_pos=0x7f77f7f6601a "", data_end=0x7f77f7f6601a "", query=0x7f7879e29f00) at /data/new56/event/DB/sql/sql_prepare.cc:937
#1  0x000000000081eb0c in Prepared_statement::set_parameters (this=0x7f77e8c56280, expanded_query=0x7f7879e29f00, packet=0x7f77f7f6600e "\v\342\a\v\002\n\005\065\370\334\f", packet_end=0x7f77f7f6601a "")
    at /data/new56/event/DB/sql/sql_prepare.cc:3594
#2  0x000000000081ebeb in Prepared_statement::execute_loop (this=0x7f77e8c56280, expanded_query=0x7f7879e29f00, open_cursor=false, packet=0x7f77f7f6600a "", packet_end=0x7f77f7f6601a "")
    at /data/new56/event/DB/sql/sql_prepare.cc:3655
#3  0x000000000081c845 in mysqld_stmt_execute (thd=0x7f77f7f62000, packet_arg=0x7f77f7f66001 "\001", packet_length=25) at /data/new56/event/DB/sql/sql_prepare.cc:2701
#4  0x00000000007f972a in dispatch_command (command=COM_STMT_EXECUTE, thd=0x7f77f7f62000, packet=0x7f77f7f66001 "\001", packet_length=25) at /data/new56/event/DB/sql/sql_parse.cc:1351
#5  0x00000000007f8931 in do_command (thd=0x7f77f7f62000) at /data/new56/event/DB/sql/sql_parse.cc:1060
#6  0x00000000007be7d1 in do_handle_one_connection (thd_arg=0x7f77f7f62000) at /data/new56/event/DB/sql/sql_connect.cc:998
#7  0x00000000007be2ab in handle_one_connection (arg=0x7f77f7f62000) at /data/new56/event/DB/sql/sql_connect.cc:905
#8  0x0000000000b2f665 in pfs_spawn_thread (arg=0x7f7877ffd920) at /data/new56/event/DB/storage/perfschema/pfs.cc:1860
#9  0x00007f7879b6d9d1 in start_thread () from /lib64/libpthread.so.0
#10 0x00007f78788d68fd in clone () from /lib64/libc.so.6
(gdb) p *query
$1 = {Ptr = 0x7f77e8c15040 "insert into test values(?)", str_length = 26, Alloced_length = 32, alloced = true, str_charset = 0x182f260}
(gdb) n
940	    length+= res->length()-1;
(gdb) p *query
$2 = {Ptr = 0x7f77e8c1c070 "insert into test values('2018-11-02 10:45:17')", str_length = 46, Alloced_length = 48, alloced = true, str_charset = 0x182f260}

        可以看到,在937行把问号做了替换,还原了sql语句,而问号里的值在上面 param->set_param_func函数中获取,set_param_func在此实际调用的是set_param_datetime,代码如下:

static void set_param_datetime(Item_param *param, uchar **pos, ulong len)
{
  MYSQL_TIME tm;
  ulong length= get_param_length(pos, len);//前端发过来的参数长度

  if (length >= 4)
  {//下面把前端发过来的参数转成MYSQL_TIME时间
    uchar *to= *pos;

    tm.neg=    0;
    /*
     前端发过来时间格式数字内存转的字符串:20181101125510124566,代表的时间为2018年11月01日12点55分10秒124566微秒
     分别用2字节存年,月日时分秒均用1个字节存,微秒4字节,一共2+1+1+1+1+1+4=11字节,前端发过来的时间
     格式就是按这个方式把数据堆在一起,下面的逻辑就是把时间还原出来   
    */
    tm.year=   (uint) sint2korr(to);
    /*
     sint2korr(A) (int16) (((int16) ((uchar) (A)[0])) + ((int16) ((int16) (A)[1]) << 8))
     把两个字节所表示的整数还原出来,下面sint4korr把四字节表示的整数还原出来
    */
    tm.month=  (uint) to[2]; //0~255之间值一个字节可以存放
    tm.day=    (uint) to[3];
    if (length > 4)
    {
      tm.hour=   (uint) to[4];
      tm.minute= (uint) to[5];
      tm.second= (uint) to[6];
    }
    else
      tm.hour= tm.minute= tm.second= 0;

    tm.second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0;
  }
  else
    set_zero_time(&tm, MYSQL_TIMESTAMP_DATETIME);

  /*
   此时打印时间是带精度的:
   (gdb) p tm
   $9 = {year = 2018, month = 11, day = 2, hour = 10, minute = 45, second = 17, second_part = 908000, neg = 0 '\000', time_type = 32632}
  */
  param->set_time(&tm, MYSQL_TIMESTAMP_DATETIME,
                  MAX_DATETIME_FULL_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
  *pos+= length;
}

        至此,在set_param_datetime中把前端传过来的时间参数转成了tm时间,并在param->set_time设置到了value中,param->set_time函数如下:

void Item_param::set_time(MYSQL_TIME *tm, timestamp_type time_type,
                          uint32 max_length_arg)
{ 
  DBUG_ENTER("Item_param::set_time");

  value.time= *tm;           //保存时间
  value.time.time_type= time_type;

  if (check_datetime_range(&value.time))
  {
    make_truncated_value_warning(ErrConvString(&value.time,
                                               MY_MIN(decimals,
                                                      DATETIME_MAX_DECIMALS)),
                                 time_type);
    set_zero_time(&value.time, MYSQL_TIMESTAMP_ERROR);
  }

  state= TIME_VALUE;
  maybe_null= 0;
  max_length= max_length_arg;
  decimals= 0;            //精度设为0,不管原来值是多少,一律清0,关键点=================
  DBUG_VOID_RETURN;
}

        再回到 insert_params_with_log函数,在上面的937行上面两行调用 param->query_val_str 函数把tm时间转成了时间值字符串:

const String *Item_param::query_val_str(THD *thd, String* str) const
{
  switch (state) {  //state值为TIME_VALUE
  case INT_VALUE:
    str->set_int(value.integer, unsigned_flag, &my_charset_bin);
    break;
  case REAL_VALUE:
    str->set_real(value.real, NOT_FIXED_DEC, &my_charset_bin);
    break;
  case DECIMAL_VALUE:
    if (my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value,
                          0, 0, 0, str) > 1)
      return &my_null_string;
    break;
  case TIME_VALUE://==========>进入
    {
      char *buf, *ptr;
      str->length(0);
      /*
        TODO: in case of error we need to notify replication
        that binary log contains wrong statement 
      */
      if (str->reserve(MAX_DATE_STRING_REP_LENGTH+3))
        break; 

      /* Create date string inplace */
      buf= str->c_ptr_quick();
      ptr= buf;
      *ptr++= '\'';
      /*
        这里decimals在前面set_time中被设置成了0,MY_MIN(decimals, DATETIME_MAX_DECIMALS)为
        取小值,因此 my_TIME_to_str(&value.time, ptr,MY_MIN(decimals, DATETIME_MAX_DECIMALS))
        等价于my_TIME_to_str(&value.time, ptr,0) ,传入的精度位数为0,my_TIME_to_str函数是把时间
        转成字符串,如果精度为0直接忽略秒以下值
      */
      ptr+= (uint) my_TIME_to_str(&value.time, ptr,
                                  MY_MIN(decimals, DATETIME_MAX_DECIMALS));
      *ptr++= '\'';
      str->length((uint32) (ptr - buf));
      break;
    }
  case STRING_VALUE:
  case LONG_DATA_VALUE:
    {
      str->length(0);
      append_query_string(thd, value.cs_info.character_set_client, &str_value,
                          str);
      break;
    }
  case NULL_VALUE:
    return &my_null_string;
  default:
    DBUG_ASSERT(0);
  }
  return str;
}

        在my_TIME_to_str中又是直接调用my_datetime_to_str把时间转成的字符串逻辑如下:

//l_time 待转的时间
//to 存转换后的时间字符串
//dec 精度
int my_datetime_to_str(const MYSQL_TIME *l_time, char *to, uint dec)  
{
  int len= TIME_to_datetime_str(to, l_time); //TIME_to_datetime_str仅转换年月日时分秒
  if (dec) //精度不为0则进入把精度转换处理
    len+= my_useconds_to_str(to + len, l_time->second_part, dec);
  else  //精度为0则直接舍弃秒以下精度。前面已经将精度置为0,这种场景下,每次都走这个else逻辑分支,直接忽略秒以下精度
    to[len]= '\0';
  return len;
}

        整个逻辑可以非常清楚的看到,sql层在处理这种情况传过来的时间参数时,直接把时间的秒以下精度丢掉生成一个时间字符串,给binlog和general log还原问号生成sql语句,因此binlog中的sql语句时间是直接忽略精度,非四舍五入的。

三、InnoDB引擎时间去处

        上面已经证明了猜测的一半,sql层还原语句直接丢弃了秒以下的精度。而从结果上来看,innodb层应该是做了四舍五入,究竟是不是这么做的呢?可以继续跟踪。在row_insert_for_mysql函数打断点,往回追踪,最终是在函数 my_datetime_round中处理的时间,如果没有指定精度,会根据传过来的实际参数值是否有秒以下精度来做四舍五入,大于0.5秒的会向前取整加一秒,有兴趣的同学可以跟踪看一下,这里不再细述。

总结

        真实原因和猜测的一样,sql层和引擎层处理精度逻辑不一样,一个直接舍弃,一个四舍五入,造成了相差一秒的情况,有的时候,合理的假设往往能做到有的放矢,避免乱碰乱撞,达到事半功倍的效果。知道了根本原因要修复也比较简单,即可以都舍去,也可以都四舍五入,逻辑保持一致即可。下载最新版官方代码复现时发现官方已经修复了这个问题,5.6 & 6.7都已经修复,都使用了四舍五入的逻辑,因此用户可以使用新版本避免这个问题。当然如果不想手工改代码修复,又不想升级最新版本,以下几个方法也可以避免这个问题:

  1. 前端时间类型秒以下精度清0,前端取到的时间是有微秒精度的,清零之后再发到后台。
  2. 使用binlog用row模式。
  3. 不用预解编译定变量模式(useServerPrepStmts=false)。

后续

mysql 官方5.7.18、5.6.36 修复了该bug。附官方commit说明:


SHA-1: 6b3d07f3343a1fe7039cfc5fb8b6da092ccde793

* BUG#25187670: BACKPORT BUG#19894382 TO 5.6 AND 5.7.

Backport from mysql-trunk to mysql-5.6 and mysql-5.7.

Bug#19894382 SERVER SIDE PREPARED STATEMENTS LEADS TO POTENTIAL
             OFF-BY-SECOND TIMESTAMP ON SLAVE

For temporal type input parameter (as time, timestamp and
datetime) of server side prepared statement, the fractional
second part is ignored while preparing the query string.
Executing such query string at slave is resulting in a time
value difference between master and server.

For server prepared statement, the parameters passed for
execution are parsed and Item_param objects are created for
it. While preparing Item_param for temporal types time,
timestamp and datetime, precision for fractional second part's
(Item_param::decimals) is set to "0" always. Because of which
while preparing query string with param values, fractional second
value is ignored. So execution of such prepared statements uses
correct values but query string formed is incorrect. Hence
difference in temporal type value is observed on usage of query
string.
Fix:
--------
If temporal types time, timestamp and datetime has fractional
second part then setting microseconds (6 digit) precision for
the Item_param.
机器学习实战26-一种基于LightGBM的股市涨跌预测系统与代码实现过程 在全球经济一体化的背景下,股市作为经济活动的晴雨表,其波动与预测对于投资者、金融机构乃至国家政策制定者而言至关重要。随着金融市场的日益复杂化与信息量的爆炸式增长,股市分析不再仅限于基本面和技术面的传统研究,而是迫切需要更加精准、高效及智能化的方法来捕捉市场动态,以辅助决策制定。模型评估是确保LightGBM股市预测系统准确性和稳定性不可或缺的一环。通过综合运用多种评估指标、科学的验证方法以及深入的性能分析,我们不仅能够全面理解模型的能力和限制,还能为持续优化模型、提升预测准确性奠定坚实基础。 阅读详情

相关推荐

利用CubeMX复现正点原子TFTLCD驱动例程

①准备delay.c、delay.h、sys.c和sys.h四个文件。FMC的工作原理暂时先欠着,先记录一下CRUD的过程。这里我们使用的是BANK1 的第一个分区。点击 Configuration->FMC。②把fmc自动生成的代码注释掉一部分。配置参数如下图 17.5.1。③这个printf语句要屏蔽掉。选项卡之下配置相关参数。④整体代码,按需裁剪。

qq_59757948的博客 1613

解决时间字段存入MySQL数据库时间差一秒的问题

在使用公司封装的数据库映射工具保存数据到mysql数据库,保存的数据时间是2022-08-10 12:29:28,调用通用查询方法查出的结果是2022-08-10 12:29:29,另外一条数据保存时间2022-08-10 12:35:01,查询结果又一致,时好时不好,数据不一致导致后续业务异常。time : 默认格式:HH:mm:ss 范围1:不写年月日时,-838:59:59/838:59:59 范围2: 写年月日时, -23:59:59/23:59:59。修改数据保存时的时间。

青鸟飞鱼 2341

FFmpeg HDR视频转SDR视频命令

之前蓝光盘电影多是AVC 1080p 8bit SDR格式视频,近两年4K电影流行,下载的蓝光电影多是HEVC 2160p 10bit HDR视频格式。 ffprobe查看有如下属性: # 10bit HDR Stream #0:0(eng): Video: hevc (Main 10), yuv420p10le(tv, bt2020nc/bt2020/smpte2084), 3840x2160 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn, 23.98

彼此当年少,莫负好时光 1万+

MySQL 同一条查询语句不同查询条件运行时间相差1秒

同一条查询语句不同查询条件运行时间相差1秒 异常背景 测试同事在验证某一列表功能时,点击不同的两个行对应的弹窗操作,有明显的响应时间的差异 异常查询 查看SQL执行计划 mysql&gt; explain SELECT * FROM `db_group` WHERE act_id = 980 and is_del = 0 ORDER BY group_id DESC LIMIT 0, 15...

走在命运的左岸 1666

开放平台 - 互动玩法演进之路

随着直播业务和用户规模日益壮大,如何丰富直播间内容、增强直播间内用户互动效果,提升营收数据变得更加关键。

bilibili_TC的博客 1742

别再为域名备案发愁了!微信小程序后端调用,试试这个‘官方捷径’——云托管

本文介绍了微信小程序后端部署的新思路——利用微信云托管服务绕过域名备案难题。通过详细的环境准备、数据库配置、服务部署和小程序端调用方案,帮助开发者快速实现小程序与后端服务的无缝对接,大幅缩短上线周期并降低运维成本。

weixin_29243279的博客 679

java代码中和mysql数据库中时间相差1秒问题?

mysql数据库的时间总是比代码中的时间多一秒。

qq_44097642的博客 134

R语言机器学习:XGBoost线性回归模型的SHAP值

SHAP(SHapley Additive exPlanations)值是一种基于博弈论Shapley值的机器学习模型解释方法,能够解释任何模型的预测结果。其主要用途包括:1)提高模型的可解释性,帮助非技术用户理解模型预测;2)识别对模型预测最重要的特征,辅助特征选择;3)调试模型,发现预测中的异常;4)评估模型公平性,避免偏见。SHAP值的计算方法包括初始化、迭代计算、归一化和解释,常用工具如Python的shap库支持多种计算方式(如TreeSHAP、KernelSHAP等)。本文还提供了基于R语言计算

专注生信领域 3444

java 编程中 Date 与 SimpleDateFormat 时间转换不一致问题 与 SimpleDateFormat 线程安全问题

前提说明: java.util.Date中的getTime函数定义如下:      java.util.Date代表一个时间点,其值为距公元1970年1月1日 00:00:00的毫秒数。所以它是没有时区和Locale概念的。      public long getTime() 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒...

qq_38243970的博客 4445

TMF8801 ToF激光测距传感器原理图设计,已量产(距离传感器)

这张 TMF8801 小板的外围结构就很有代表性。核心传感器是 U1 TMF8801,但真正构成量产价值的是外围那一圈:U2 把 VCC 整理成 3V,R1/R2/R5 与 R3/R4/R6 两组 10K 电阻稳定默认态,Q2 2N7002 和 U3 SN74LVC2G07DCKR 处理控制链路,传感器边上还有 C1/C4/C5 三颗 100nF 紧贴去耦。

不脱发的程序猿 163

SAP RAP 里的 EML 全解:从语言定位到事务语义,再到真实案例的落地方式

摘要:EML(Entity Manipulation Language)是ABAP RAP模型的核心组件,作为ABAP的子集用于操作业务对象(BO)。它通过声明式语法(READ/MODIFY/EXECUTE/COMMIT)统一访问BO的行为与数据,并由RAP运行时自动处理校验、锁定、草稿管理等生命周期。EML将业务语义融入代码,确保与Fiori应用共享同一套校验逻辑,并通过FAILED/REPORTED/MAPPED管道传递错误与消息。其事务控制(IN LOCAL MODE与COMMIT ENTITIES)

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 528

[实战]MySQL时间多了一秒

同时保存一条数据在MySQL和Redis中,JAVA系统中显示Redis和MySQL数据差了一秒,即MySQL比Redis中快了一秒。

知识搬运工 513

Avalonia+ReactiveUI跨平台路由:从零到舞者,你的UI也能跨界起舞?

至此,你已掌握了Avalonia+ReactiveUI的跨平台路由精髓!你的应用现在能够优雅地在各个界面间穿梭,就像是在不同星球间跳跃的宇宙飞船。无论是初探跨平台开发的新手,还是经验丰富的老船长,这段旅程都能让你的UI编排技能更上一层楼。现在,是时候让世界见证你的跨平台魔术了!💫记住,每一次实践都是向着完美编舞迈进的一步,勇敢地在你的项目中尝试吧!如果在航行中遇到风暴,别忘了回来看看这篇指南,或者在评论区抛出你的救生圈,我们一起解决!🌊。

java专栏 1536

datetime计算秒数差需要注意的问题

python

ningyanggege的博客 530

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

mybatis存入时间与java的Date时间差1秒

由于Java处理时间,如果没有毫秒,直接舍弃,而mybatis是存入精确时间,取出时会四舍五入,差一秒,当时间毫秒>500时,会出现mybatis取出时间比Java时间多1秒

weixin_45850480的博客 583

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

MySQL中timestamp默认值current_timestamp默认时间和系统时间不一致问题

因为在设计表结构时候,把这两个时间的属性设置为了timestamp类型并,设置了默认值CURRENT_TIMESTAMP,这样在对数据进行插入或修改时就可以直接默认插入当前时间。但问题出现了,当我进行前后端联调测试的时候发现并未插入当前系统时间,问题无非就出现在前端,后端,数据库这三个方面,前端和后端均为设计这两个字段的插入操作,当然除了使用命令修改之外还可以再配置文件中修改,在虚拟机中找到配置文件位置进行修改保存。在写后端接口时并没有对create_time和update_time进行字段插入。

weixin_66590942的博客 3312

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

date存入mysql中时,多了一秒的解决方案

    mysql中字段类型为datetime,java代码中存入2018-09-26 11:06:56时,到了数据库中值会变为2018-09-26 11:06:57 具体原因本人还没有验证,参照别人的博客,可能的原因如下:   1、因为数据库驱动升级,导致的。 //将时间精度转换为秒 Date ss = DateUtils.round(now, Calendar.SECOND);   ...

w592376568的博客 3109

mybatis时间字段存入mysql数据库时间差一秒的问题

解决方案 其实很简单,将数据库字段中datetime长度从0调整至3即可。 问题原因 因为Java的Date类对象获取的时间是以带着小数的毫秒数传入数据库的,而当数据库datetime设置长度为0时,会自动根据毫秒数后面的小数进行四舍五入,会导致时间精度的缺失。当把数据库字段的长度设置为3时,数据库则会保留毫秒数的三位小数,则不会导致时间精度的丧失。这个问题小会引起时间校正的不准确,大则到生成的密钥无法准确校验,所以不可忽视。 ...

涛哥是个大帅比 1187

获取TimeStamp的时间差

TimeStamp求时间差的方式的记录 最近在写相关时间类型的方法,对时间类型(Date,Time,SimpleDateFormat,TimeStamp)进行使用。 收集整理 SimpleDateFormat parse方法:将字符串类型(java.lang.String)解析为日期类型(java.util.Date) format方法:将日期类型(Date)数据格式化为字符串(String)...

Jerry的博客 1万+

MySQL主从同步相关-主从多久的延迟?

这次单独调查一下主从延迟的时间。这里说的主从延迟,并不是指“从库更新性能跟不上主库”, 而是“一个命令从主库更新完成到从库更新完成的延迟时间。   基本流程: 对于每一个连上来的从库,主库都有一个client线程与之对应。 先看主从的基本数据流 1、客户端SQL更新命令 2、主库执行 3、主库写binlog 4、主库client线程读binlog发送给从库的io线程 5、从库io

很多时候,你缺少的不是知识而是热情 2481

postgresql内核开发之add_months函数实战

postgresql内核开发之add_months函数实战 前文通过实现helloworld,简单上手postgresql内核开发。 本文承接上文,通过在postgresql内核中实现oracle内置函数add_months进一步揭示postgresql内核开发中添加内置函数的原理及方法。 src/include/catalog/pg_proc.h中新增代码: DATA(ins

postgres20的博客 9128

postgresql源码阅读快速上手

postgresql源码阅读,从windows下postgresql源码调试入手。postgresql 报错如何跟代码?ereport与elog比有什么区别?

postgres20的博客 8122

telnet 测试MySQL时通时不通问题分析

telnet探活MySQL时通时不通现象分析。

postgres20的博客 6894

postgresql内核语法解析器详解

postgresql内核语法解析器详解概述前面博文中谈过parser语法解析模块,但没深入介绍,本文相对详细的介绍下,对postgresql语法解析模块初步揭密。

postgres20的博客 6589

postgresql 10 分区探密

postgresql官方终于要出分区了,开发线上已经看到提交分区代码了,下一个版本postgresql 10版本带有分区功能基本是没问题了,那么这个分区功能如何呢?且和我深入源码一探究竟。

postgres20的博客 4950

PG_dump 源码笔记

PG_DUMP 源码简析   pg_dump是一个用于备份PostgreSQL 数据库的工具。它甚至可以在数据库正在使用的时候进行完整一致的备份。pg_dump并不阻塞其它用户对数据库的访问(读或者写)。 转储格式可以是一个脚本或者归档文件。脚本转储的格式是纯文本,它包含许多 SQL 命令,这些 SQL 命令可以用于重建该数据库并将之恢复到保存成脚本的时候的状态。使用psql从这样的脚本中恢复

postgres20的博客 4270
上一篇: 诡象追踪:MySQL开binlog性能更好?!
下一篇: innodb不同场景下加锁分析总结
postgres20
博客等级 码龄10年 100粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值