Server side prepared statements leads to potential off-by-second timestamp on slaves
Affects | Status | Importance | Assigned to | Milestone | ||
---|---|---|---|---|---|---|
MySQL Server |
Unknown
|
Unknown
|
||||
Percona Server moved to https://jira.percona.com/projects/PS | Status tracked in 5.7 | |||||
5.5 |
Invalid
|
Undecided
|
Unassigned | |||
5.6 |
Triaged
|
Medium
|
Unassigned | |||
5.7 |
Triaged
|
Medium
|
Unassigned | |||
8.0 |
Fix Committed
|
Medium
|
Unassigned |
Bug Description
I have Percona Server 5.6.21 installed on RHEL6, the following packages:
Percona-
Percona-
Percona-
I have the following table:
> show create table test.t1\G
*******
Table: t1
Create Table: CREATE TABLE `t1` (
`created_time` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Testcase:
> truncate test.t1;
Query OK, 0 rows affected (0.02 sec)
Run the following code using mysql-connector
import java.sql.
import java.sql.Timestamp;
import java.sql.
import java.sql.
class Test {
public static void main(String[] args) {
Connection conn;
try {
String url = "jdbc:mysql:
conn = DriverManager.
} catch (Exception e) {
}
}
}
Note the result in the table:
> select * from test.t1\G
*******
created_time: 2011-03-23 12:28:54
Now, run the same code, but without server-side prepared statements in the driver options:
import java.sql.
import java.sql.Timestamp;
import java.sql.
import java.sql.
class Test {
public static void main(String[] args) {
Connection conn;
try {
String url = "jdbc:mysql:
conn = DriverManager.
} catch (Exception e) {
}
}
}
Inspect the database again; result is as expected:
> select * from test.t1\G
*******
created_time: 2011-03-23 12:28:54
*******
created_time: 2011-03-23 12:28:54
However, now examine the binary/replication log on the server (binlog_
#141016 9:16:23 server id 9993 end_log_pos 7065 CRC32 0x08aa0438 Query thread_id=81 exec_time=0 error_code=0
SET TIMESTAMP=
INSERT INTO t1 (created_time) values ('2011-03-23 12:28:53')
/*!*/;
# at 7065
#141016 9:16:23 server id 9993 end_log_pos 7096 CRC32 0x11ceda38 Xid = 1268
COMMIT/*!*/;
# at 7096
#141016 9:18:13 server id 9993 end_log_pos 7183 CRC32 0xad39e8c8 Query thread_id=83 exec_time=0 error_code=0
SET TIMESTAMP=
BEGIN
/*!*/;
# at 7183
#141016 9:18:13 server id 9993 end_log_pos 7329 CRC32 0x039bbb0b Query thread_id=83 exec_time=0 error_code=0
SET TIMESTAMP=
INSERT INTO t1 (created_time) values ('2011-03-23 12:28:53.501')
/*!*/;
# at 7329
#141016 9:18:13 server id 9993 end_log_pos 7360 CRC32 0x6c565aeb Xid = 1282
COMMIT/*!*/;
Note that the for the first test, while using server-side prepared statements, the fractional part of the timestamp was dropped before getting to the binary log. When not using server-side prepared statements (2nd test), the fractional part of the timestamp is preserved into the binary log. From the timestamps in the table, you can see the problem. With server-side prepared statements the master will end up with the correctly rounded timestamp ('2011-03-23 12:28:54'), but any slave will end up with the truncated timestamp, which in this case is 1 second behind ('2011-03-23 12:28:53').
The workaround of not using server-side prepared statements is not an option. In our case we have alleviated the issue by rounding the timestamp in the code to the nearest second, but this should really "just work".
I have not looked deeper into whether this is a JDBC driver or a server issue.
Changed in percona-server: | |
assignee: | nobody → Muhammad Irfan (muhammad-irfan) |
Changed in percona-server: | |
status: | New → Confirmed |
assignee: | Muhammad Irfan (muhammad-irfan) → nobody |
tags: | added: upstream |
Verified that this also happens with the newest mysql-connector -java (5.1.33)