github.com/matrixorigin/matrixone@v1.2.0/pkg/txn/trace/README_CN.md (about) 1 ## Txn trace framework 2 在MO的版本迭代过程中,可能会遇到各种事务正确性问题,比如 Duplicate 和 W-W Conflict 问题。 3 4 这些问题通常依靠日志和错误信息去分析很困难,通常会花费开发人员非常多的时间,因为Debug事务正确性问题是相当困难的。很多时候,这些问题可能非常难以复现。 5 6 事务trace框架就是为了是为了快速定位事务正确性问题而设计的。 7 8 9 ## 设计思考 10 ### Trace哪些数据 11 结合之前分析事务正确性问题的经验,我们通常需要如下的一些信息: 12 13 * 事务元数据 14 15 事务的元数据,以及每次元数据变更的信息。毫无疑问,这个信息是非常重要的。至少包括了,事务的snapshot ts,commit ts等 16 17 * 事务Read的数据 18 19 事务在执行过程中,所有读到数据的内容和版本 20 21 * 事务Commit的数据 22 23 事务Commit到TN的数据内容 24 25 * Logtail数据 26 27 CN收到的Logtail是什么,包括数据内容,以及顺序。 28 29 * 事务正确性错误 30 31 已知的事务正确性的错误,内部包含发现问题的table以及row的信息。 32 33 * 冲突处理 34 35 在悲观模式下,会发生锁冲突,冲突的处理的信息。这些信息决定了事务会不会lost update. 36 37 当我们具备了这些信息,并且按照发生的时间顺序排列,那么我们就具备了我们分析问题的所有信息,理论上只要发生了问题,我们就可以找到问题所在。 38 39 ### 存储和访问 40 Trace的数据量是很大的,如何存储和使用这些数据决定了分析问题的难度。 41 42 分析问题的时候,我们需要检索数据,以及根据一些条件来过滤数据,最好的访问方式就是SQL。 43 44 一旦我们决定使用SQL来访问这些trace数据,那么这些数据自然而然的就应该存储在MO自己的内部表中。 45 46 ## 设计方案 47 48 ### Trace数据内部表 49 50 #### Features 51 ```sql 52 create table trace_features ( 53 name varchar(50) not null primary key, 54 state varchar(20) not null 55 ); 56 ``` 57 58 * txn 59 60 跟踪事务的生命周期中,事务元数据的变化事件。 61 62 开启:`select mo_ctl('cn', 'txn-trace', 'enable txn')` 63 64 关闭:`select mo_ctl('cn', 'txn-trace', 'disable txn')` 65 66 67 * data 68 69 跟踪数据的变化事件,比如commit,apply logtail,flush等。 70 71 开启:`select mo_ctl('cn', 'txn-trace', 'enable data')` 72 73 关闭:`select mo_ctl('cn', 'txn-trace', 'disable data')` 74 75 * txn-action 76 77 跟踪事务的生命周期中,所有动作的开销(耗时,读的数据块个数等等)。 78 79 开启:`select mo_ctl('cn', 'txn-trace', 'enable txn-action')` 80 81 关闭:`select mo_ctl('cn', 'txn-trace', 'disable txn-action')` 82 83 * txn-workspace 84 85 跟踪事务的生命周期中,workspace的所有数据变更。 86 87 开启:`select mo_ctl('cn', 'txn-trace', 'enable txn-workspace')` 88 89 关闭:`select mo_ctl('cn', 'txn-trace', 'disable txn-workspace')` 90 91 * statement 92 93 跟踪满足条件的statement的耗时。用于和txn-action特性配合,跟踪statement执行的每个阶段的开销,以便于性能调优。 94 95 开启:`select mo_ctl('cn', 'txn-trace', 'enable statement')` 96 97 关闭:`select mo_ctl('cn', 'txn-trace', 'disable statement')` 98 99 100 #### Trace数据 101 ```sql 102 create table trace_event_txn ( 103 ts bigint not null, 104 txn_id varchar(50) not null, 105 cn varchar(100) not null, 106 event_type varchar(50) not null, 107 txn_status varchar(10), 108 snapshot_ts varchar(50), 109 commit_ts varchar(50), 110 info varchar(1000) 111 ) 112 113 create table trace_event_data ( 114 ts bigint not null, 115 cn varchar(100) not null, 116 event_type varchar(50) not null, 117 entry_type varchar(50) not null, 118 table_id bigint UNSIGNED not null, 119 txn_id varchar(50), 120 row_data varchar(500) not null, 121 committed_ts varchar(50), 122 snapshot_ts varchar(50) 123 ) 124 125 create table trace_event_txn_action ( 126 ts bigint not null, 127 txn_id varchar(50) not null, 128 cn varchar(50) not null, 129 table_id bigint UNSIGNED, 130 action varchar(100) not null, 131 action_sequence bigint UNSIGNED not null, 132 value bigint, 133 unit varchar(10), 134 err varchar(100) 135 ) 136 137 create table trace_event_error ( 138 ts bigint not null, 139 txn_id varchar(50) not null, 140 error_info varchar(1000) not null 141 ) 142 143 create table trace_statement ( 144 ts bigint not null, 145 txn_id varchar(50) not null, 146 sql varchar(1000) not null, 147 cost_us bigint not null 148 ) 149 ``` 150 151 * trace_event_txn 152 153 事务事件表,记录了事务元数据的变更数据,以及事务的锁冲突处理的信息。`txn` feature 打开的时候生效。 154 155 * trace_event_data 156 157 数据读写事件表,所有事务读取的数据,commit的数据以及Logtail的事件数据。`data` feature 打开的时候生效。 158 159 * trace_event_txn_action 160 161 事务动作表,记录了事务生命周期内,所有动作的信息,包含了这些动作的开销(执行耗时,数据块个数等等)。`txn-action` feature 打开的时候生效。 162 163 * trace_event_error 164 165 事务正确性错误的事件数据表。这个表是我们查询事务正确性问题的起点。找到出问题的事务以及数据分析。`txn` feature 打开的时候生效。 166 167 遇到有复合主键的,使用`select mo_ctl('cn', 'txn-trace', 'decode-complex complex_pk_value')`来解码。 168 169 * trace_statement 170 171 statement表,满足条件的statement会记录,包括sql内容,耗时,以及事务 172 173 #### Filters 174 ```sql 175 create table trace_table_filters ( 176 id bigint UNSIGNED primary key auto_increment, 177 table_id bigint UNSIGNED not null, 178 table_name varchar(50) not null, 179 columns varchar(200) 180 ); 181 182 create table trace_txn_filters ( 183 id bigint UNSIGNED primary key auto_increment, 184 method varchar(50) not null, 185 value varchar(500) not null 186 ); 187 188 create table trace_statement_filters ( 189 id bigint UNSIGNED primary key auto_increment, 190 method varchar(50) not null, 191 value varchar(500) not null 192 ); 193 ``` 194 195 过滤条件表,支持按照表,事务以及statement的条件过滤,用来trace需要关注的事务和数据。 196 197 * trace_table_filters 198 199 表数据过滤,一行记录对应一张表,可以同时创建多条记录,用来trace多个表。columns字段不设置,trace这个表的所有的字段。`存在多行记录,满足任意一行的数据都会被trace;0行记录,不会对数据进行trace`。 200 201 增加表所有列: `select mo_ctl('cn', 'txn-trace', 'add-table table_name')` 202 203 增加表指定列: `select mo_ctl('cn', 'txn-trace', 'add-table table_name col1,col2')`,多个col用`,`分割 204 205 清理:`select mo_ctl('cn', 'txn-trace', 'clear data')` 206 207 刷新:`select mo_ctl('cn', 'txn-trace', 'refresh data')` 208 209 210 * trace_txn_filters 211 212 事务过滤,一行记录代表一个对于事务的约束,可以同时创建多个约束,`当存在多行记录的时候,必须所有的约束都满足,事务才会被trace;0行记录,不会对事务进行trace`。 213 214 过滤指定用户的事务:`select mo_ctl('cn', 'txn-trace', 'add-txn user user_name')` 215 216 过滤指定租户的事务:`select mo_ctl('cn', 'txn-trace', 'add-txn tenant account_id user_name')` 217 218 过滤指定session的事务:`select mo_ctl('cn', 'txn-trace', 'add-txn session session_id')` 219 220 过滤指定connection的事务:`select mo_ctl('cn', 'txn-trace', 'add-txn connection session_id connection_id')` 221 222 清理:`select mo_ctl('cn', 'txn-trace', 'clear txn')` 223 224 刷新:`select mo_ctl('cn', 'txn-trace', 'refresh txn')` 225 226 * trace_statement_filters 227 228 statement过滤,一行记录代表一个statement的约束,可以同时创建多个约束,`当存在多行记录的时候,必须所有的约束都满足,statement才会被trace;0行记录,不会对statement进行trace`。 229 230 过滤执行时间超过阈值的statement:`select mo_ctl('cn', 'txn-trace', 'add-statement cost value[us|ms|s|m|h]')` 231 232 过滤包含关键字的statement:`select mo_ctl('cn', 'txn-trace', 'add-statement contains value)` 233 234 清理:`select mo_ctl('cn', 'txn-trace', 'clear statement')` 235 236 刷新:`select mo_ctl('cn', 'txn-trace', 'refresh statement')` 237 238 239 ### Trace数据如何写入 240 trace数据如果实时写入,那么这个性能是糟糕的,几乎不可用。所以我们采取异步写入的方式。 241 242 我们的CN节点都会带有一个本地磁盘,所以使用本地磁盘作为cache,使用load csv文件的方式,写入trace数据。 243 244 使用单线程的方式,采用顺序写的方式写入trace数据到CSV文件,写满一定大小(默认16M),flush到磁盘,并且load到MO。